In unit tests, sometimes you just need to do some simple work with a mock. Something like setting an identifier on an argument that is passed in to the mock.
Imagine a service interface where this is one of the methods:
void createObject(MyObject objectToCreate)
Now imagine that on that same interface there are many other methods that you do not care about. How would you go about creating a mock object that only cares about that one method?
For example, here is a method you want to test:
public MyObject createOrUpdate(MyObject myObject) { try { ObjectService service = getObjectService(); if(service.findMyObject(myObject.identifier) == null) { service.createObject(myObject); } else { service.updateObject(myObject); } return myObject; } catch(Exception e) { //handle Errors } }
Using a mocking framework such as Mockito, you would need to do something like this:
public void testCreateObject() { ObjectService mockService = mock(ObjectService.class); when(mockService.createObject(any(MyObject.class))). thenAnswer(new Answer<void>(){ @Override Void answer(InvocationOnMock invocation) throws Throwable { invocation.getArguments()[0].setIdentifier(1); return null; } }); ObjectWorker sut = new ObjectWorker(); sut.setObjectService(mockService); assertEquals(1, sut.createOrUpdate(new MyObject()).getIdentifier()); }
That obviously works fine, but it isn’t very pretty and it is very verbose. The fact is that mocking frameworks (or at least Mockito) just aren’t designed to work directly on arguments that are passed into the mocks. That’s kind of the point. Mocks are supposed to answer up some canned or recorded responses. They aren’t supposed to do real work.
But what if I want to do real work, but I don’t want to have to implement the entire interface? Well, if you are using Groovy, you are in luck. Here is a bit of code that does the same thing, only with some Groovy magic:
def void testCreateObject() { def service = [ createObject: { myObject -> myObject.identifier = 1} ] as ObjectService def sut = new ObjectWorker(objectService: service) assert sut.createOrUpdate(new MyObject()).getIdentifier() == 1 }
What just happened? We are essentially casting a map of closures as an ObjectService. When methods are called on this object, Groovy does some magic under the covers to see if the method call matches one of the defined closures. If it does match, it executes that closure.
To me, this is a much more concise way of doing some work inside of a mock object.
Originally Posted on my Blogger site November of 2013