не могу понять взаимодействие Спока

Вот модульный тест, который отлично работает.

@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
}

тогда заглушка метода на самом деле не возвращает фиктивный объект соединения, как предполагалось. Для меня это более естественный поток выражений. Однако то же самое в блоке «тогда» работает так, как задумано. Не знаю, что здесь происходит. Не могу найти соответствующее обсуждение в сети. Я также могу опубликовать это на 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);

}

person apil.tamang    schedule 30.07.2015    source источник
comment
Можете ли вы показать именно код, который не работает ... вы просто показываете код, который он есть. С целым изображением может быть проще   -  person juandiegoh    schedule 30.07.2015


Ответы (2)


Если вы хотите вернуть какой-либо объект, вы должны вместо этого использовать заглушку.

@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

Надеюсь, поможет!

person juandiegoh    schedule 30.07.2015
comment
хм... но он должен уметь определять заглушки и для фиктивного объекта, не так ли? - person apil.tamang; 30.07.2015
comment
только что попробовал еще раз, и это не так! жаль, что я не могу загрузить изображение или что-то в этом роде, чувак... но все равно спасибо за попытку. Это немного странно, не правда ли? Я на Groovy версии: 2.1.6. , spock_version = 0.7-groovy-2.0. Какая у вас установка? - person apil.tamang; 31.07.2015
comment
Завтра постараюсь выложить код на гитхаб и поделиться им с вами - person juandiegoh; 31.07.2015

Следующие работы:

@Subject([WeatherServiceImpl.class,URLConnection.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

}

person apil.tamang    schedule 30.07.2015