TDD: Mock expectations in Setup
One of the ideas that I mentioned in a recent post about what I consider to be a good unit test was the ideas that we shouldn’t necessarily consider the DRY (Don’t Repeat Yourself) principle to be our number one driver.
I consider putting mock expectations in the setup methods of our tests to be one of those occasions where we shouldn’t obey this principle and I thought this would be fairly unanimously agreed upon but putting the question to the Twittersphere led to mixed opinions.
The case for expectations in setup
The argument for putting expectations in the setup method is that it helps remove duplication and helps us to fail more quickly.
This would certainly be the case if, for example, we instantiated our object under test in the setup method and there were some expectations on its dependencies on creation.
The case against expectations in setup
The reason I’m so against putting expectations in setup methods derives from the pain of trying to debug NMock error messages when we put expectations and stubs in the setup method on a project I worked on about a year ago.
The number of times we were caught out by a failure which seemed 'impossible' from looking at the failing test was ridiculous.
After that experience we made sure that it was always obvious which expectations belonged to which test by inlining them and taking the duplication hit.
I believe a lot of the value of tests comes from the way that they fail, and if we can write tests in a way that the failure message and subsequent fix are really obvious then we are going the right way.
My current approach
My current approach to try and get the best of both worlds is to follow the approach Phil describes in his post on Domain Driven Tests.
If we have repeated expectations across different tests then I now try to extract those into an appropriately named methods which can be called from each test.
[Test]
public void ShouldDoSomething()
{
ExpectServiceToReturnSomeValue();
// rest
// of
// test
}
private void ExpectServiceToReturnSomeValue()
{
// code describing expectations
}
This creates a little bit of duplication in that we have to call this method individually in each test which uses it but I think it makes the test more readable and easier to debug.
I’m still not sure what I consider the best way to name these types of methods - Phil uses a combination of a comment and method name to create readable tests but I’m keen to try and have the intent completely described by a method name if possible.
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.