In this recipe, we will stub a method that is a void method. It doesn't return a value, so it calls a real method. This way, we will construct a partial mock (to read more about partial mocking, please refer to Chapter 2, Creating Mocks).
For this recipe, our system under test will be the same class as in the previous recipe, but let's take another look at it so that you don't need to scroll around to see the source code. The PersonProcessor
class, for simplicity, does only one thing: it delegates the process of saving person
to the PersonSaver
class. As shown in the following code, in case of success, true is returned; otherwise, false is returned:
public class PersonProcessor { private final PersonSaver personSaver; public PersonProcessor(PersonSaver personSaver) { this.personSaver = personSaver; } public boolean process(Person person) { try { personSaver.savePerson(person); return true; } catch (FailedToSavedPersonDataException e) { System.err.printf("Exception occurred while trying save person data [%s]%n", e); return false; } } }
Contrary to the previous recipe, PersonSaver
is a class and not an interface. This verifies whether the person's origin is defined. If that is not the case, then FailedToSavedPersonDataException
will be thrown.
If you want your void method to call real methods upon calling the void method, you need to perform the following steps:
BDDMockito.willCallRealMethod().given(mock).methodToStub()
, or in the standard way, call Mockito.doCallRealMethod().when(mock).methodToStub()
.given(...)
or when(...)
method, you have to provide the mock object (and not the method call like in case of methods that return values).willCallRealMethod().willNothing().given(personSaver).savePerson(smith);
This example shows you how to make your void method call the real method only once, and then do nothing, by default. Regardless of the number of personSaver.savePerson(...)
method executions, first the real implementation will be called, and then you will always have no further execution (until it is stubbed again).
Let's check the JUnit test. See Chapter 1, Getting Started with Mockito, for the TestNG configuration (remember that I'm using BDDMockito.given(...)
and AssertJ's BDDAssertions.then(...)
static methods. Check out Chapter 7, Verifying Behavior with Object Matchers, for more details on how to work with AssertJ or how to do the same with Hamcrest's assertThat(...)
):
@RunWith(MockitoJUnitRunner.class) public class PersonProcessorTest { @Mock PersonSaver personSaver; @InjectMocks PersonProcessor systemUnderTest; @Test public void should_fail_to_save_person_data_due_to_having_undefined_country() { // given willCallRealMethod().given(personSaver).savePerson(any(Person.class)); // when boolean updateSuccessful = systemUnderTest.updatePersonData(new Person()); // then then(updateSuccessful).isFalse(); } }
Remember that if you need to create a partial mock, and if you really don't have some strong arguments to back that decision up, then you should rethink the architecture of your program or your tests since it most likely is not the best quality. Please refer to Chapter 3, Creating Spies and Partial Mocks, for more details.
Please refer to the Stubbing void methods recipe for more information on the Mockito internals related to stubbing void methods.
What's worth mentioning is that the answer-taking part in the Mockito internal delegation process is the CallsRealMethod
answer.
doReturn()
|doThrow()
|doAnswer()
|doNothing()
|doCallRealMethod()
family of methods at http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Mockito.html#123.144.9.124