The following code:
ObjectMapper mapper = Mockito.mock(ObjectMapper.class);
Mockito.doThrow(new IOException()).when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject());
Mockito.doNothing().when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject());
try {
mapper.writeValue(new ByteArrayOutputStream(), new Object());
} catch (Exception e) {
System.out.println("EXCEPTION");
}
try {
mapper.writeValue(new ByteArrayOutputStream(), new Object());
} catch (Exception e) {
System.out.println("EXCEPTION");
}
The expected output is
EXCEPTION
right?
But I get nothing
If I then make the doThrow after the doNothing I get
EXCEPTION
EXCEPTION
So It looks like it is the last mock that is the one that is taken... I thought it would take the mocks in the order they're registered?
I'm looking to produce a mock throws the exception first time and completes normally the second time...
Mockito can stub consecutive behavior with the same parameters—forever repeating the final instruction—but they all have to be part of the same "chain". Otherwise Mockito effectively thinks you've changed your mind and overwrites your previously-mocked behavior, which isn't a bad feature if you've established good defaults in a setUp
or @Before
method and want to override them in a specific test case.
The general rules for "which Mockito action will happen next": The most-recently-defined chain that matches all arguments will be selected. Within the chain, each action will happen once (counting multiple thenReturn
values if given like thenReturn(1, 2, 3)
), and then the last action will be repeated forever.
// doVerb syntax, for void methods and some spies
Mockito.doThrow(new IOException())
.doNothing()
.when(mapper).writeValue(
(OutputStream) Matchers.anyObject(), Matchers.anyObject());
This is the equivalent of chained thenVerb
statements in the more-common when
syntax, which you correctly avoided here for your void
method:
// when/thenVerb syntax, to mock methods with return values
when(mapper.writeValue(
(OutputStream) Matchers.anyObject(), Matchers.anyObject())
.thenThrow(new IOException())
.thenReturn(someValue);
Note that you can use static imports for Mockito.doThrow
and Matchers.*
, and switch to any(OutputStream.class)
instead of (OutputStream) anyObject()
, and wind up with this:
// doVerb syntax with static imports
doThrow(new IOException())
.doNothing()
.when(mapper).writeValue(any(OutputStream.class), anyObject());
See Mockito's documentation for Stubber for a full list of commands you can chain.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With