无法理解spock交互

时间:2015-07-30 18:45:28

标签: spock

这是一个运行良好的单元测试。

@Subject([WeatherServiceImpl.class,URLConnection.class])
class WeatherServiceImplSpec extends Specification{

    def "First spock test I ever wrote"(){

        given: "some mock objects"

        //1. define mock HttpURLConnection object
        def mockConnObj=Mock(HttpURLConnection.class)

        //2. defn of another mock
        def mockURLAdaptor=Mock(URLAdapter)

        when: "define some calls"
        def test=new WeatherServiceImpl(mockURLAdaptor)
        test.run("Raleigh")

        then: "make some assertions"
        1*mockURLAdaptor.openConnection(_)>>mockConnObj
        1*mockConnObj.getResponseCode()


    }//end def test
}

我不明白的是,如果我在“给定”块中执行此操作:

def mockURLAdaptor = Mock(URLAdapter) >> {

​        openConnection(_) >> mockConnObj
}

然后方法存根实际上不会按预期返回模拟连接对象。对我而言,这是更自然的表达方式。然而,在'then'块中执行相同的操作可以按预期工作。不知道这里发生了什么。似乎无法在网上找到相关的讨论。我也可以在stackoverflow上发布这个。

这是受测试的课程:

package com.icidigital.services.impl

import com.icidigital.Helpers.URLAdapter
import com.icidigital.services.IWeatherService

public class WeatherServiceImpl implements IWeatherService {

    private URLAdapter urlAdapter;

    private URLConnection urlConn;

    public WeatherServiceImpl(URLAdapter urlAdapter){

        //injecting this dependency, so I can unit test
        //by injecting a mock URLAdapter instance. In
        //normal operation, urlAdaptee would be an instance
        //of URLWrapper, which simply wraps around the
        // URL class, which is a final class and cannot
        // be mocked normally.

        this.urlAdapter=urlAdapter;
    }

    public String run(String city){
        ...
        ..
        urlConn=urlAdapter.openConnection(city);

        //(throws a null pointer exception while spock-ing)
        urlConn.setRequestMethod("GET");


    }
}

这是公开方法的url适配器:openConnection。在运行代码中,有一个类URLWrapper,它简单地包装在java.net.URL类中。我需要做到这一点,以解决我无法直接模拟java.net.URL类的事实,因为它是最后一个类。

interface URLAdapter {

    public HttpURLConnection openConnection(String cityName);

}

2 个答案:

答案 0 :(得分:1)

如果你想返回一些对象,你应该使用Stub。

@Subject([WeatherServiceImpl.class,URLConnection.class])
class WeatherServiceImplSpec extends Specification{

    def "First spock test I ever wrote"(){

        given: "some mock objects"

        //1. define mock HttpURLConnection object
        def mockConnObj=Mock(HttpURLConnection.class)

        //2. defn of another mock
        def mockURLAdaptor=Stub(URLAdapter)
        mockURLAdaptor.openConnection(_)>>mockConnObj

        when: "define some calls"
        def test=new WeatherServiceImpl(mockURLAdaptor)
        test.run("Raleigh")

        then: "make some assertions"
        1*mockConnObj.getResponseCode()


    }//end def test
}

你也可以用Mocks来做,我只是尝试了这个并且它有效

def "First spock test I ever wrote"() {
        given: "some mock objects"

        //1. define mock HttpURLConnection object
        def mockConnObj = Mock(HttpURLConnection.class)

        //2. defn of another mock
        def mockURLAdaptor = Mock(URLAdapter)
        1 * mockURLAdaptor.openConnection(_) >> mockConnObj

        when: "define some calls"
        def test = new WeatherServiceImpl(mockURLAdaptor)
        test.run("Raleigh")

        then: "make some assertions"
        1 * mockConnObj.getResponseCode()
}//end def test

希望它有所帮助!

答案 1 :(得分:0)

以下工作:

@subject([WeatherServiceImpl.class,URLConnection.class]) class WeatherServiceImplSpec扩展了规范{

def "First spock test I ever wrote"(){

    given: "some mock objects"

    //1. define mock HttpURLConnection object
    def mockConnObj=Mock(HttpURLConnection.class)
    //=========================================
    //2. defn of another mock

    // Either/Or:
    //def mockURLAdaptor=Mock(URLAdapter) 
    def mockURLAdaptor=Stub(URLAdapter)

    //followed by:
    mockURLAdaptor.openConnection(_)>>mockConnObj

    //OR

    def mockURLAdaptor=Stub(URLAdapter){
        openConnection(_)>>mockConn
    }

    //BUT NOT:

    def mockURLAdaptor=Mock(URLAdapter){
        openConnection(_)>>mockConn
    }
    //=========================================

    when: "define some calls"
    def test=new WeatherServiceImpl(mockURLAdaptor)
    test.run("Raleigh")

    then: "make some assertions"
    1*mockConnObj.getResponseCode()


}//end def test

}