In this recipe, we will stub a void method that doesn't return a value, so it throws an exception.
For this recipe, our system under test will be a PersonProcessor
class that, 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; } } }
If you want your void method to throw an exception upon calling, you need to perform the following steps:
BDDMockito.willThrow(exception).given(mock).methodToStub()
, or in the standard way, call Mockito.doThrow(exception).when(mock).methodToStub()
.given(...)
or when(...)
method, you have to provide the mock object (and not the method call in the case of methods that return values).willThrow(new Exception1()).willThrow(new Exception2()).given(personSaver).savePerson(smith);
Then, regardless of the number of personSaver.savePerson(...)
method executions, first Exception1
will be thrown, and then you will always have Exception2
thrown (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_when_exception_occurs() { // given willThrow(FailedToSavedPersonDataException.class).given(personSaver).savePerson(any(Person.class)); // when boolean updateSuccessful = systemUnderTest.process(new Person()); // then then(updateSuccessful).isFalse(); } }
Please refer to the Stubbing void methods recipe for more information on the Mockito internals that are related to stubbing void methods.
What's worth mentioning is that the answers that take part in the Mockito internal delegation process are either ThrowsExceptionClass
or ThrowsException
answers.
doReturn()
|doThrow()
|doAnswer()
|doNothing()
|doCallRealMethod()
family of methods at http://docs.mockito.googlecode.com/hg/1.9.5/org/mockito/Mockito.html#1218.191.168.203