跨测试框架的公用测试

程序越来越大,工具越来越多,在同一个项目中碰到要用不同的测试框架来进行测试的情况也不可避免会发生。如何是好呢?ldaley.com上有一贴给出了一种解决方案

我目前所在项目存在Spock和JUnit混用的情况,大多数测试还要求共享上下文。我的解决方案是使用“测试支持对象(test support object)”而非直接继承超类。(注:说白了就是把测试的实际内容都提取出来单独用一个类封装,这样就可以在各个测试框架中调用并共享)。这似乎并不稀奇,但是如果你需要依赖注入,这种方法就比较有趣了。

来看看这所谓的“test support class”长啥样:

import org.codehaus.groovy.grails.commons.ApplicationHolder

class TestSupport { 
    
    @Lazy fixtureLoader = getBean('fixtureLoader')
    @Lazy someOtherService = getBean('someOtherService')
    
    protected getBean(name) {
        ApplicationHolder.application.mainContext[name]
    }
    
    def loadFixture(fixtureParams) {
        // load fixture here
    }
    
    // Other common methods and stuff
}
为什么要用ApplicationHolder来获取application context和bean呢?主要是为了避免产品和测试代码混淆,把TestSupport类放在tests/integration下,这意味着我们不能把它搞成service。我们也不能选择性的经由grails-app/conf/resource.groovy创建一个自动装配实例,因为在tests/integration中的类对与处理装载application context的classloader来说是不可见的。尽管使用静态holder也让我不爽,但这是我们能让其工作的唯一工具。

下面看看Spock下如何使用该test support class:

import grails.plugin.spock.*

class SomeSpec extends IntegrationSpec {
    
    @Delegate TestSupport testSupport = new TestSupport()
    
    def "some stuff should happen"() {
        given:
        loadFixture(/* fixture options */)
        when:
        someOtherService.doStuff()
        then:
        someOtherService.stuffHappened
    }
    
    def "some other stuff should happen"() {
        given:
        loadFixture(/* fixture options */)
        when:
        someOtherService.doOtherStuff()
        then:
        someOtherService.otherStuffHappened
    }
}

By songwei - Posted on 21 五月 2010