美文网首页开源工具技巧DTeam团队日志每周500字
Vert.x入坑须知(4.1):用Spock写异步测试

Vert.x入坑须知(4.1):用Spock写异步测试

作者: 胡键 | 来源:发表于2018-12-29 19:47 被阅读43次

    点进来的老读者可能会对系列的数字感到奇怪:为何不是5而是4.1?实话是,本篇内容足够重要,可以算得上入坑必须了解的内容。但从篇幅上来讲它实在又有点单薄,而我最近也没时间憋个大招去写长篇大论,权衡之下干脆采用小数计位,赶在18年最后一个工作日完稿。

    之前在本系列的第三篇,我曾提到我们团队采用的测试框架是Spock,也提到了为何我们坚持使用这个框架,即使是在Vert.x已经对测试有支持的情况下。

    对于非异步场景,Spock工作得很好,写测试的效率也很高。对于异步场景,之前我们一直采用的策略是加上“必要的sleep”。就这样凑合了不短的时间之后,终于团队内有小伙伴开始抱怨了。

    这也很容易理解,由于机器配置的不同,sleep的时间很难把握得恰到好处。往往出现在一台机器上可以跑过的测试而在另一台机器上跑不过,再加上我们要求必须有自动化测试代码并配置了pipeline,这样一来自然就有人受不了啦。

    本着解决根本问题的精神,再辅以高超的搜索大法,最终我们摸索出了一套用Spock来测试vertx异步场景的方法。说来惭愧,这个方法一直就在那里,只是我们一直没有特别重点的去关注:Spock对于异步测试的支持。

    对于异步场景,Spock已经提供了3个测试辅助类:

    • BlockingVariable
    • AsyncConditions
    • PollingConditions

    BlockingVariable

    顾名思义,这个类的作用就是一直阻塞,直到有值。它非常适合测试异步回调返回值的测试场景,如下例,测试一个数据库的返回值。

    when:
    BlockingVariable<Integer> rowCount = new BlockingVariable<>()
    BlockingVariable<String> callback = new BlockingVariable<>()
    pgUtils.simpleSql(NamedQuery.uncalledCallback) { rowSet ->
        rowCount.set(rowSet.size())
        callback.set(rowSet.asList()[0].getString('callback'))
    }
    
    then:
    rowCount.get() == 1
    callback.get() == 'callback2'
    

    rowCount.get()会一直阻塞,直到其检测到有值,这样就避免的无谓的sleep。

    AsyncConditions

    这个类用于测试异步条件是否,如下面的例子:

    setup:
    conditions = new AsyncConditions(1)  // 其中的数字为需要evaluate的个数,缺省为1
    String source = "foo.txt";
    String target = "bar.txt";
    createFileWithJunk(source, 100);
    
    when:
    vertx.fileSystem().copy("$testDir$pathSep$source", "$testDir$pathSep$target") {
        conditions.evaluate {
            assert new File(testDir, source).exists()
            assert new File(testDir, target).exists()
        }
    }
    
    then:
    conditions.await();
    

    在这个例子中,await将一直处于阻塞状态,直到evaluate部分的代码满足条件。但它的缺点也很明显,整个测试并不那么“spock style”,整个验证过程都放在了when部分。

    PollingConditions

    这个类的作用跟AsyncConditions非常类似,但它弥补了后者的不足,如下例:

    setup:
    def conditions = new PollingConditions(timeout: 10, initialDelay: 1.5, factor: 1.25)
    def machine = new Machine()
    
    when:
    machine.start()
    
    then:
    conditions.eventually {
        assert machine.temperature >= 100
        assert machine.efficiency >= 0.9
    }
    

    从上面的代码可以看出来,验证部分就在then部分,完美。

    总结

    至此,Spock的这些工具类非常好地解决了vertx的异步场景测试问题,而且gradle输出的测试报告来看,测试时间也比之前要省不少!

    那么,这些工具类也可以用于测试其他的异步场景么?当然,从上面的代码看,所有测试只依赖Spock的异步测试工具类,与vertx完全无关!并且,对于每个测试工具类,Spock也提供了超时机制,具体细节可以参看它们的JavaDoc


    本系列其他文章:

    相关文章

      网友评论

        本文标题:Vert.x入坑须知(4.1):用Spock写异步测试

        本文链接:https://www.haomeiwen.com/subject/whvplqtx.html