1. Overview

In this tutorial, we’re going to look at defining multiple expectations on a mock. We can configure methods on a mock object to return some controlled value. In this case, mock object will always return the same value. However, we can also configure the mock to return a value on the first invocation and some other value on the second invocation.

2. Sample Application

Let’s start with our sample application.

Firstly, we’ve PersonRepository which manages data access operations. Secondly, we’ve PersonService which includes PersonRepository as a dependency:

public class PersonService {
    private final PersonRepository personRepository;
    public PersonService(PersonRepository personRepository) {
        this.personRepository = personRepository;
    }
    public Person update(Person person) {
        return personRepository.update(person);
    }
}
public class PersonRepository {
    public Person update(Person person) {
        return person;
    }
}

3. Multiple Expectations On A Mock

Mockito enables us to create expectations in the form of when().thenReturn() statements. There are also other variants in the Mockito API.

When we configure a mock method with only one behavior, all invocations of that method will return the same value. However, there can be cases where we need to return different values on different invocations. We can achieve this by chaining the expectations:

@InjectMocks
private PersonService personService;

@Mock
private PersonRepository personRepository;

@Test
public void shouldDefineMultipleExpectations() {
    Person firstExpected = new Person("first");
    Person secondExpected = new Person("second");
    Mockito.when(personRepository.update(Mockito.any(Person.class))).thenReturn(firstExpected).thenReturn(secondExpected);

    Person firstPerson = personService.update(new Person("test"));

    Assertions.assertThat(firstPerson).isEqualTo(firstExpected);

    Person secondPerson = personService.update(new Person("test"));

    Assertions.assertThat(secondPerson).isEqualTo(secondExpected);
}

Here, we have 2 cascaded thenReturn() statements. When we first call the update() method of PersonRepository, it will return firstExpected. When it is called again, it will return secondExpected.

But be aware that rewriting the expectation with a different value doesn’t give the same result:

@Test
public void shouldNotDefineMultipleExpectations() {
    Person firstExpected = new Person("first");
    Person secondExpected = new Person("second");
    Mockito.when(personRepository.update(Mockito.any(Person.class))).thenReturn(firstExpected);
    Mockito.when(personRepository.update(Mockito.any(Person.class))).thenReturn(secondExpected);

    Person firstPerson = personService.update(new Person("test"));
    // Will fail!
    Assertions.assertThat(firstPerson).isEqualTo(firstExpected);

    Person secondPerson = personService.update(new Person("test"));

    Assertions.assertThat(secondPerson).isEqualTo(secondExpected);
}

Here we’re not chaining thenReturn() calls, instead, we’re overriding the expected return value.

4. Summary

We’ve looked at how we can define multiple expectations and return values using Mockito.

As always, the source code is available on Github.

Leave a Reply

Close Menu