我正在尝试在集成测试中模拟对外部服务的调用,该服务用于grails webflow。该服务不在流或会话范围内,但是通过依赖注入添加,请参阅here。
我设法通过使用ExpandoMetaClass替换它的metaClass来找到覆盖服务的方法。这些更改仅在单独运行测试时有效,如果在此测试之前运行了使用相同服务的另一个测试,则metaClass更改将消失。
覆盖metaClass的部分:
static {
ExpandoMetaClass someService = new ExpandoMetaClass(Object, false)
someService.invokeMethod = { String name, args ->
def result = 'success'
if(name.equals('accessAnotherSystem')
{
StackTraceUtils.sanitize(new Throwable()).stackTrace.each
{
if(it.methodName.equals('test_method_I_Want_failure_in')
{
result = 'exception'
}
}
return result
}
def validMethod = SomeService.metaClass.getMetaMethod(name, args)
if (validMethod != null)
{
validMethod.invoke(delegate, args)
}
else
{
SomeService.metaClass.invokeMissingMethod(delegate, name, args)
}
}
someService.initialize()
SomeService.metaClass = someService
}
相关问题:How to change a class's metaClass per test
有没有办法保留我对测试的更改,或者是否有其他方法来覆盖服务。
答案 0 :(得分:0)
如果要在每个测试方法中覆盖测试用例中的服务,有一种更简单的方法。看一个例子:
class SomeControllerSpec extends Specification {
def someService
void "test any external method for success response"() {
given: "Mocked service method"
someService.metaClass.accessAnotherSystem = { arg1, arg2 ->
return "some success response"
}
when: "Any controller method is called which calls this service method"
// Your action which calls that service method
then: "Result will processed coming from mocked method"
// Your code
}
}
对于任何服务测试方法,您都可以这样做。如果你想模拟你正在编写测试用例的相同服务的方法,那么在这里哟去..
class SomeServiceSpec extends Specification {
def someService
void "test external method call"() {
given: "Mocked service method"
someService.metaClass.methodA = { arg1, arg2 ->
return "some success response"
}
when: "A method is called which invokes the another method"
// Your another service method which call the same method
someService.methodB() // Where methodB() invokes the methodA() internally in your code
then: "Result will processed coming from mocked method"
// Your code
}
}