这是一个运行良好的单元测试。
@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);
}
答案 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
}