These days testing interactions is getting very common. Mocking tools are becoming a necessary supplement to xUnit libraries precisely to facilitate testing interactions. I cannot imagine writing software without assert() (to test state) and verify() (to test interactions).
I’m about to show that it is very useful to distinguish two basic kinds of interactions: asking an object of data and telling an object to do something. Fair enough, it may sound obvious but most mocking frameworks treat all interactions equally and don’t take advantage of the distinction.
Let’s have a look at this piece of code:
Before mocking was invented we manually wrote stubs and tests looked like this:
Sometimes I miss those days before mocking. Test code looked so nice… The only problem was that hand writing every stub was quite cumbersome and produced tons of extra code.
Anyway, let’s try to extract a pattern from above test code:
1. when the repository is asked to find “foo” article, then return article
3. make sure repository was told to delete article
So, to generalize it:
Now, let’s put it into words:
Interaction that is asking an object for data (or indirect input) is basically providing necessary input for processing. This kind of interaction is meant to be stubbed before running code under test (exercising the behaviour).
Interaction that is telling an object to do something (or indirect output) is basically the outcome of processing. This kind of interaction is meant to be asserted after running code under test.
Testing interactions like that is more natural and produces better code. Lessons learned from the old ways of testing interactions are implemented in Mockito:
Above approach may seem controversial (quoting interesting para):
Then, when you do verify(…), you have to basically repeat the exact same expression you put in stub(…). This might work if you only have a couple calls to verify, but for anything else, it will be a lot of repeated code, I’m afraid
Basically, the controversy is about repeating the same expression in stub() and verify():
Do I really have to repeat the same expression? After all, stubbed interactions are verified implicitly. The execution flow of my own code does it completely for free. Aaron Jensen also noticed that:
If you’re verifying you don’t need to stub unless of course that method returns something that is critical to the flow of your test (or code), in which case you don’t really need to verify, because the flow would have verified.
Just to recap: there is no repeated code.
But what if an interesting interaction shares the characteristic of both asking and telling? Do I have to repeat interactions in stub() and verify()? Will I end up with duplicated code? Not really. In practice: If I stub then it is verified for free, so I don’t verify. If I verify then I don’t care about the return value, so I don’t stub. Either way, I don’t repeat myself. In theory though, I can imagine a rare case where I do verify a stubbed interaction, for example to make sure the stubbed interaction happened exactly n times. But this is a different aspect of behavior and apparently an interesting one. Therefore I want to be explicit and I am perfectly happy to sacrifice one extra line of code…
Mockito recognises the difference between asking and telling, hence stubbing is separated from verification. Stubbing becomes a part of setup whereas verification a part of assertions. This produces cleaner code and gives more natural testing/TDD. It doesn’t increase code duplication as one might think. It’s just one of the ideas implemented in Mockito to make the mocking experience a little bit better. It’s not a silver bullet, though. Decent code is easily testable regardless of any mocking tools.