Mockito: Verifying Details of an Object Passed to a Collaborator

Recently I was BDD’ing a class, and the behavior I needed to describe happened to be an object created internally (a simple value object) populated with a few attributes and passed to a collaborator. The old way I might be tempted to do this is just create a concrete implementation of the collaborator that stores the argument passed to it, then get it back and verify some outcome on it.

But I wondered if there was a way to do it with Mockito without it looking crappy. And apparently there is a way to verify values on an argument to a collaborator using ArgumentCaptor.


First, let’s create a rather contrived example for illustration. Say we have some kind of application where we have a method that adds users to some kind of CMS. Now lets also assume we have some kind of event mechanism in place and we want to fire a USER_ADDED event with the User that was added attached to it so that handlers can respond to this event. Essentially, we want to ensure that the collaborator (in this case the EventPublisher) receives an Event with certain attributes that it should have.

For starters, let’s define an interface for the EventPublisher:

public interface EventPublisher {
	void publish(Event event);
}

And a few minor classes for the collaboration process:

public class Event {
	private EventType type;
	private Object data;
}
public enum EventType {
	USER_ADDED, USER_CREATED
}

With this in place, I’ll write an example (or unit test if you’re not sold on BDD nomenclature yet) to illustrate how to verify the EventType USER_ADDED was fired:

@RunWith(MockitoJUnitRunner.class)
public class AdministrativeUserServiceSpec {
	@Mock EventPublisher publisher;
	private AdministrativeUserService administrators;
	private ArgumentCaptor argument;
	@Before
	public void before(){
		administrators = new AdministrativeUserService(publisher);
		argument = ArgumentCaptor.forClass(Event.class);
	}
	@Test
	public void shouldFireAnEventOfTypeUserAddedWhenNewUserIsAdded(){
		User user = new User();
		
		administrators.add(user);
		
		verify(publisher).publish(argument.capture());
		assertEquals(EventType.USER_ADDED, argument.getValue().getType());
	}
}

I will say, I’m not too fond of the forced verify call to capture the argument as it creates a bit of noise! To get this mess to compile before we pass the example, we first create the object and it’s signatures:

public class AdministrativeUserService {
	private final EventPublisher publisher;
	public AdministrativeUserService(EventPublisher publisher) {
		this.publisher = publisher;
	}

	public void add(User user) {
		// logic to actually "add" user omitted
	}
}

Run it and the example fails. So we go ahead and implement the details of the method to fire an event:

	public void add(User user) {
		Event event = new Event();
		event.setType(EventType.USER_ADDED);
		publisher.publish(event);
	}

Rerun the example and… yep! It passes. Now we also write a new example (since we should only focus on one outcome at a time) that illustrates the User instance being included in the event being fired:

	@Test
	public void shouldFireAnEventWithTheUserThatWasAddedAsData(){
		User user = new User();
		
		administrators.add(user);
		
		verify(publisher).publish(argument.capture());
		assertSame(user, argument.getValue().getData());
	}

Naturally, the model doesn’t fit the example and it fails… so lets just add the one line needed to fit into the example:

	public void add(User user) {
		// logic to actually "add" user omitted
		Event event = new Event();
		event.setType(EventType.USER_ADDED);
		event.setData(user);
		publisher.publish(event);
	}

Awesome, it passes! Now lets step back over the example line by line so we can illustrate what is going on here (because I know the ArgumentCaptor’s syntax confused me in the documentation):

ArgumentCaptor argument = ArgumentCaptor.forClass(Event.class);

This is the factory method to create an instance of the argument captor for the Event type. I’ve named it argument so that it reads better later (as I will explain). Nothing special here… just creating the instance for use in the example.

verify(publisher).publish(argument.capture());

Here, we’re using the ArgumentCaptor to capture the argument that gets passed to the publish invocation. As you can see, the naming pays off as it reads like it’s capturing the argument (which IS what it is doing after all). The way it works is it has already captured the arguments of any methods called on the mock (thanks to proxying) and stored them for access… but by calling the capture method in this way it sets the argument being “looked at” to the one that was passed to the publish method. Whew!

assertEquals(EventType.USER_ADDED, argument.getValue().getType());

Nothing special here… getValue() simply returns the argument that was captured, in this case the Event that was published.

Hope this helps you like it helped me… before I figured this out, I was copping out and was creating a hard coded mock of the EventPublisher… adding a bit of ugly looking code to the specification. That always feel repetitive. ;)

  • http://spockframework.org Peter Niederwieser

    For Java, that’s probably the best that can be achieved. Groovy + Spock are even more succinct:

    class AdministrativeUserServiceSpec extends Specification {
    def publisher = Mock(EventPublisher)
    def administrators = new AdministrativeUserService(publisher)

    def “should fire an event of type user_added when new user is added”() {
    def user = new User()

    when:
    administrators.add(user)

    then:
    1 * publisher.publish({ it.type == EventType.USER_ADDED })
    }
    }

  • http://blog.james-carr.org James Carr

    Thanks Peter… I was unaware of Spock and now I’ll have to check it out. ;)

  • Srinivasa Reddy

    Thanks James.. I was exactly searching for it.