Sometimes you want to mock the behaviour of a class to give different responses to each invocation of a method.
For example, if you wanted to arrange a test to verify the ability of a class; Syncer
to recover from a RuntimeException
thrown by a service it uses, your test might look a bit like this:
So you run this test and it fails. Not always a bad thing when developing tests; at least you know it’s doing something! But in this case, the test case is failing on this line:
This isn’t an assertion, so we’ve likely got something wrong in our test arrangement.
The error indicates that we’re actually throwing a RuntimeException
from our test.
So what’s going on and what can we do about it?
Well, the problem lies in the fact that in our attempt to mock the getApiData
method for a second time, we are, perhaps surprisingly, invoking that method and getting the RuntimeException
we told it to throw in our previous mocking. It’s right there!
To fix this we need to define both mock invocations without triggering the mocked method behaviour.
Luckily we can do this safely by chaining the mocking declarations like this:
This prevents the RuntimeException
from being thrown prematurely and makes our test case neater too:
We can chain as many mock behaviours as we like, although if you have more than a few it might be worth thinking about the complexity of the class you are trying to test.
Thanks for reading!
This post is Creative Commons Attribution 4.0 International (CC BY 4.0) licensed.