美文网首页程序员
如何使用 Spock 测试 Static Method

如何使用 Spock 测试 Static Method

作者: _WZ_ | 来源:发表于2016-11-09 09:37 被阅读1264次

    Spock 简易使用说明

    使用 Spock 来开发测试程式除了在之前的文章中提到的:可辅助 BDD 的开发流程、与 JUnit 相容及内建 Data Driven 功能等特性之外,还有另外一项优点是内建了 Mock 的功能。Spock 所提供的 Mock 功能在使用上相当的简洁,以下是一段范例的源代码:

    def "Spock 范例测试程式"() {
        given:
        def mockClass = Mock(ConcreteClass)
        def mockInterface1 = Mock(IInjection)
        IInjection mockInterface2 = Mock()
        Processor tester = new Processor(mockClass)
    
        mockInterface2.getInfo() >> { "二号测试字串" }
    
        when:
        tester.run(mockInterface1)
    
        then:
        1 * mockClass.start()
        1 * mockInterface1.getInfo() >> { "一号测试字串" }
        _ * mockClass.process(_) >> { mockInterface2 }
        1 * mockInterface2.setData(_)
        1 * mockClass.end()
    }
    

    由以上的源代码可以看到只要使用 Mock() 方法就可以对指定的对象进行 Mock 的程序,同时也提供二种弹性的声明方式,一是把要 Mock 的对象传入 Mock() 方法(第 3, 4 行),另一个方式是使用 Mock() 方法来建立实例(第 5 行)。第二种 Java-like 的语法主要是希望在编辑源代码时 IDE 可以提供较好的支持,运行时会以声明的型别来判定要产生的 Mock 对象之 Instance。

    Spock 所提供的 Mock 功能有另一个亮点是不仅能够针对 Interface,同时也可以使用在一般的 Class 上。如此在进行系统设计时,就可以不用迁就 “是否有办法分开测试” 这个问题而要使用大量的 IoC 在设计之中,以致形成了过度设计的情况。在 Mock Class 前,项目必须要引用 cglib-nodep 和 objenesis 这二个库,所以在 build.gradle 的 dependencies 应该像以下所示范的内容:

    dependencies {
        testCompile 'org.codehaus.groovy:groovy-all:2.4.4'
        testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
        testCompile 'org.objenesis:objenesis:2.2'
        testCompile 'cglib:cglib-nodep:3.1'
    }
    

    根据官方文件的说明,如果要验证目标 Class 与其周边 Object 互动的过程是否符合像是序列图所表达的设计内容,可以使用范例程式中所示范之内容。使用的语法规格是:[互动的次数] * [互动的标的],1 * mockClass.start() 就是验证 Processor.run 是否有调用 ConcreteClass.start(),而且整个 Processor.run 的运行过程中只调用一次。

    从范例程式中还可以看到,Spock 所提供的 Mock 功能,除了可以用来验证 Class 间互动过程,同时也具有 Stub 的能力。可以依据调用的内容来提供对应的动作,增加了测试程式的灵活性。像范例程式中的第 8 行,当有程式调用 mockInterface2.getInfo() 时,就会固定传回 "二号测试字串" 的内容。而在第 15, 16 行,是代表当 Processor.run 的运行过程中,有调用到这二个目标函式时所会取得的内容。

    如何 Mock 静态方法

    虽然 Spock 提供了许多优异的特性,不过,美中不足的地方是目前的版本没有办法 Mock 静态方法。在网路上看了一些讨论之后,PowerMock 似乎是一个可用来搭配 Spock 解决这个问题的框架。进一步了解发现 PowerMock 所提供的套件种类繁多,包含了与几个主流的测试框架整合的功能。而如何在 Gradle 中设定对应的套件,可以让 Spock 与 PowerMock 协同运作会是一个门槛。

    基本上要在 Spock 中使用 PowerMock 来 Mock 静态方法,会用到 JUnit、Mockito 和 PowerMock 这几个框架,这使得在设定 build.gradle 内容时更加的棘手。而在测试程式中要把这四个框架整合起来,以便能够达到 Mock 静态方法的目的,也是很费心神的一件事。

    目前网络上查到的资讯都是片断的,所以在这里把相关的资讯统整起来,做为日后研究的起点。以下是 build.gradle 的内容:

    apply plugin: 'java'
    apply plugin: 'groovy'
    
    dependencies {
        testCompile 'org.codehaus.groovy:groovy-all:2.4.4'
        testCompile 'org.spockframework:spock-core:1.0-groovy-2.4'
        testCompile 'org.objenesis:objenesis:2.2'
        testCompile 'cglib:cglib-nodep:3.1'
        testCompile 'org.mockito:mockito-core:1.10.19'
        testCompile 'org.powermock:powermock-api-mockito:1.6.2'
        testCompile 'org.powermock:powermock-module-junit4:1.6.2'
        testCompile 'org.powermock:powermock-module-junit4-rule:1.6.2'
        testCompile 'org.powermock:powermock-classloading-xstream:1.6.2'
    }
    

    以上的套件应该要依照所属框架更新的状况来调整对应的版本编号。

    在测试程式中,如果有一个以下待测的 Class:

    public class TestClass {
    
        public static String staticMethod() {
            return null;
        }
    
    }
    

    测试程式应该像以下所示范的内容来进行静态方法的测试:

    import org.junit.Rule
    import org.mockito.Mockito
    import org.powermock.api.mockito.PowerMockito
    import org.powermock.core.classloader.annotations.PrepareForTest
    import org.powermock.modules.junit4.rule.PowerMockRule
    import spock.lang.Specification
    
    @PrepareForTest([TestClass.class])
    class MockStaticMethodSpec extends Specification {
    
        @Rule
        PowerMockRule mPowerMockRule = new PowerMockRule();
    
        def "测试静态方法"() {
            setup :
            PowerMockito.mockStatic(TestClass.class)
    
            when :
            Mockito.when(TestClass.staticMethod()).thenReturn("测试用字串")
    
            then :
            TestClass.staticMethod() == "测试用字串"
        }
    
    }
    

    相关文章

      网友评论

        本文标题:如何使用 Spock 测试 Static Method

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