不明白Spock中的交互是如何工作的

时间:2015-07-31 13:17:57

标签: unit-testing groovy mocking spock

这是Groovy中一个非常简单的spock测试用例。!!此规范文件中定义的所有类/接口。 (spock中的规范文件只是一个测试用例文件)。

似乎无法理解工作流程。如何在测试用例工作流中实例化,注入和销毁模拟对象?任何帮助表示赞赏...

我遇到的特殊问题是理解交互语句:1 * mockURLAdapter.openConnection()是如何工作的。根据我的理解,这只是一个验证语句,声明使用非空参数调用方法'openConnection(_)'。如何/为什么调用此断言会导致方法weatherService.run()失败?返回的异常显示在代码中......

import spock.lang.Specification

class WeatherServiceImpl {
    private URLAdapter urlAdapter;
    private URLConnection urlConn;

    public WeatherServiceImpl(urlAdapter){
        this.urlAdapter=urlAdapter
    }

    def run(city) {
        urlConn=urlAdapter.openConnection(city)
        return urlConn.getResponseCode()

    }

}

interface URLAdapter {
    def openConnection(city)

}


class WeatherServiceImplSpec extends Specification {

    def mockURLAdapter = Mock(URLAdapter)
    def mockURLConn    = Mock(HttpURLConnection)
    def weatherService=new WeatherServiceImpl(mockURLAdapter);


    def "Need to figure out the effects of lines: 'troublesome' and 'weirdo' "() {
        given:
        mockURLConn.getResponseCode()>> 9999
        mockURLAdapter.openConnection(_)>>mockURLConn;

        when:
        def result=weatherService.run("New York")

        then:
        // Uncommenting line 'troublesome' below throws a null-pointer exception:
        // java.lang.NullPointerException: Cannot invoke method getResponseCode() on null object
        //      at WeatherServiceImpl.run(URLAdapterConnectionSpec.groovy:29)
        //      at WeatherServiceImplSpec.delivers events to all subscribers(URLAdapterConnectionSpec.groovy:54)

        // Commenting out line 'troublesome' gives no issue!!

        // Line 'troublesome':
        // 1*mockURLAdapter.openConnection(_)

        // Line 'weirdo':
        // And yet, line 'weirdo' works just fine, commented or not!(i.e. test passes, no exception thrown)!!
        1*mockURLAdapter.openConnection(_)>>mockURLConn;

        //WTH is happening! ?
        result==9999


    }

}

1 个答案:

答案 0 :(得分:2)

你指定了两次mockURLAdapter应该返回的内容以及你第二次说不返回任何内容,当然它仍然是你最后的决定。

// Line 'troublesome':
1 * mockURLAdapter.openConnection(_)

这意味着当调用openConnection(_)时不会返回任何内容。如果要指定交互,则应将其放在 then:子句

正确的做法应该是这样的:

def "Need to figure out the effects of lines: 'troublesome' and 'weirdo' "() {
        when:
        def result=weatherService.run("New York")

        then:
        1 * mockURLAdapter.openConnection(_) >> mockURLConn;
        1 * mockURLConn.getResponseCode() >> 9999

        result == 9999
}