I'm trying to mock a call to an outside service in an integration test, the service is used in a grails webflow. The service isn't in flow or conversation scope, but is added via dependency injection see here.
I've managed to figure out a way to override a service via replacing it's metaClass using ExpandoMetaClass. The changes only work when the test is ran alone, if another test that uses that same service is ran before this test, the metaClass changes are gone.
Part that overrides the 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
}
Related question: How to change a class's metaClass per test
Is there a way to keep my changes for the test, or is there some other way to override the service.
There is a simpler way if you want to override the service in your test case per test method. Look at an example:
You can do this same for any service test method. If you want to mock the method of same service for which you are writing test case then here yo go..