Grails : How I do mock other methods of a class under test which might be called internally during testing
Solution 1
For this kind of problem I actually avoid mocks and use the built-in groovyProxy ability to cast a map of closures as a proxy object. This gives you an instance with some methods overridden, but others passed through to the real class:
class SampleService {
def methodA() {
methodB()
}
def methodB() {
return "real method"
}
}
def mock = [methodB: {-> return "mock!" }] as SampleService
assert "mock!" == mock.methodA()
assert "real method" == new SampleService().methodA()
I like that only changes an instance, can be done in a single line, and doesn't mess with the metaclass of anything outside of that instance that needs to be cleaned up.
Solution 2
There are a lot of mocking alternatives with Groovy. You can see some documentation of Groovy Mocks, using Maps and Expandos instead of Mocks or using Closures instead of Mocks.
In your example, I'll use metaprogramming capabilities of Groovy.
void testMethodA() {
service = new SampleService()
service.metaClass.methodB = { -> return "what you want" }
service.methodA()
assert "your condition"
}
Ritesh M Nayak
Thoughtworker living in Bangalore, India. Interested in Information Retrieval, Distributed Systems and ICT4D. Love music and code. My Website !!! I even got myself a cool stackoverflow careers resume. You can check that out here : My resume on Stackoverflow Careers
Updated on June 11, 2022Comments
-
Ritesh M Nayak almost 2 years
I am writing a test for methodA() in a service class similar to the one given below.
Class SampleService { def methodA(){ methodB() } def methodB(){ } }
When I test methodA(), I need to be able to mock the call to methodB() when testing methodA(). I am using version 2.0.x of grails. In the 1.3.x distributions, I would write a self mock like this
def sampleServiceMock = mockFor(SampleService) sampleServiceMock.demand.methodB { -> }
But this doesn't work in the 2.0.x versions. I was wondering what are the other ways of mocking methodB() when testing methodA()
-
Ritesh M Nayak about 12 yearsI did finally use this approach to mocking. But, semantically speaking, changing a class's signature to make a test pass seems extreme :)
-
Ritesh M Nayak about 12 yearsYeah, this seems like a great way of mocking behaviors. I still miss the ability to self mock using grails' mockFor() :(
-
Domenic D. over 9 yearsBrilliant. This helped me as well as the test I had was creating Spock closures and was unable to assert the actual values returned from the controller (when mocking a service call).
-
GSAN about 7 yearsThe links( Groovy Mocks, using Maps and Expandos instead of Mocks or using Closures instead of Mocks) are not working anymore, please fix or delete them. Thanks.
-
Pila about 6 yearsWhat if the methods take in parameters. I am trying that an I keep getting;
groovy.lang.MissingMethodException: No signature of method: ... is applicable for argument types: (java.lang.String, java.lang.String)