Pad*_*ddy 8 grails mocking stub grails-orm spock
很抱歉,如果这是一个新手问题,但我非常感谢社区可以提供的关于我在Grails服务,LocationService中存储以下方法的问题的任何见解.
Location locate(String target, String locator, Application app, boolean sync = true) {
if (!target) throw new IllegalArgumentException("Illegal value for msid: " + target)
def locRequest = Request.create(target, Type.LOCATE)
if (!locRequest.save()) {
return Location.error(target, "Error persisting location request")
}
locationSource.locateTarget(target, locator, app, sync)
}
Run Code Online (Sandbox Code Playgroud)
我有一个域类,Request,以及默认的GORM方法也有一些额外的域方法,例如.下面的create()方法
@EqualsAndHashCode
class Request {
String reference
String msid
Type type
Status status
Destination destination
DateTime dateCreated
DateTime dateCompleted
static create(String msid, Type type, Destination destination = Destination.DEFAULT) {
new Request(reference: reference(type), type: type, status: Status.INITIATED, dateCreated: new DateTime())
}
Run Code Online (Sandbox Code Playgroud)
最后,我有一个Spock规范.我需要模拟默认的GORM方法,但也需要一些额外的域逻辑,例如静态创建方法,以便返回一个有效的对象,以便在被测试的代码中保留.
理想情况下,我会使用Spock模拟但我不能在这里使用它们,因为根据Peter N的下面的帖子,他们需要注入调用者,在这种情况下,请求(我试图模拟),创建作为LocationService中locate方法的局部变量:
https://groups.google.com/forum/?fromgroups=#!topic/spockframework/JemiKvUiBdo
我也不能使用Grails 2.x @Mock注释,虽然这会模拟GORM方法,但我不确定我是否可以从Request类中模拟/存储额外的静态create()方法.
因此,最后,我一直在尝试使用Groovy StubFor/MockFor方法来执行此操作,因为我相信这些将用于调用测试方法,方法是将其包装在use闭包中(如下所示).
这是测试规范:
@TestFor(LocationService)
// @Mock(Request)
class LocationServiceSpec extends Specification {
@Shared app = "TEST_APP"
@Shared target = "123"
@Shared locator = "999"
def locationService = new LocationService()
LocationSource locationSource = Mock()
def "locating a valid target should default to locating a target synchronously"() {
given:
def stub = new StubFor(Request)
stub.demand.create { target, type -> new Request(msid: target, type: type) }
stub.demand.save { true }
1 * locationSource.locateTarget(target, locator, app, SYNC) >> { Location.create(target, point, cellId, lac) }
def location
when:
stub.use {
location = locationService.locate(target, locator, app)
}
then:
location
}
Run Code Online (Sandbox Code Playgroud)
但是,当我运行测试时,虽然存根创建方法返回我的请求存根对象,但我在存根保存方法上失败:
groovy.lang.MissingMethodException: No signature of method: com.domain.Request.save() is applicable for argument types: () values: []
Possible solutions: save(), save(boolean), save(java.util.Map), wait(), last(), any()
Run Code Online (Sandbox Code Playgroud)
任何人都可以指出我在这里做错了什么或建议解决我的特定情况的最佳方法,如果需要存储其他方法以及域类的GORM方法,我不能直接注入到被测试的代码中?
先感谢您,
帕特里克
我相信你应该能够@Mock像你为GORM方法提到的那样使用Grails的注释,然后你需要手动模拟静态方法:
@TestFor(LocationService)
@Mock(Request)// This will mock the GORM methods, as you suggested
class LocationServiceSpec extends Specification {
...
void setup() {
Request.metaClass.static.create = { String msid, Type type, Destination destination = Destination.DEFAULT ->
//Some logic here
}
}
...
Run Code Online (Sandbox Code Playgroud)
使用@Mock注释时,Grails将模拟默认方法(保存/获取/动态查找器),但它不会对您添加的任何其他方法执行任何操作,因此您需要手动模拟这些方法.