Here’s the deal:
In state based testing (or return value testing) I assert that certain property has changed. I don’t care if other properties have changed – unless I explicitly write assertions for them. Great benefit of this style is the flexibility of testing: I can write small, targeted test methods. Basically, I can test what I want.
In interaction based testing I expect an interaction to happen. Even if I don’t care about other interactions I still have to expect them – to satisfy invasive mocks. This is how most mocking frameworks work and as a result, I cannot write small, targeted test methods. Basically, I cannot test what I want.
Some mocking frameworks are not invasive. Others offer tricks to reduce this problem – with various success rate and usually with side effects. Instead of jumping into examples let me ask you:
Does your mocking framework let you test what you want?
Expecting a single interaction in most mocking frameworks means: 1. this interaction must happen. 2. other interactions must NOT happen. Do you imagine if an innocent assertion of the state worked like that? Asserting one property meaning also asserting that NONE of the other properties have changed?
Let me rephrase my initial question: Why testing interactions has to be more defensive than testing state?
Is it because we fell in love with pre-programmed, intelligent mocks? Is it because of the way mocking frameworks are implemented? Or perhaps because of the strive to have a decent point of failure – mock can bark with unexpected interaction straight in the code so it’s very easy to find it?
I’m not buying it. When it comes to behaviour verification, Mockito provides excellent point of failure. Also, Mockito can detect any kind of unexpected interactions. Oh, and Mockito lets me test what I want…
Mockito mocks are tamed. They don’t make decisions for me. They don’t know which interactions are expected or unexpected. I rule my mocks. I rule my code. And it pays back generously: code is cleaner and reacts better to changes.
By now, you’ve probably figured out that Mockito is not strictly a mocking framework. It’s rather a spying/stubbing framework but that’s a story for a different post.