This is an AMP version of the article, its original content can be found here.

A Few Thoughts on Unit Test Scaffolding

When I start to repeat myself in unit test methods by creating the same objects and preparing the data to run the test, I feel disappointed in my design. Long test methods with a lot of code duplication just don't look right. To simplify and shorten them, there are basically two options, at least in Java: 1) private properties initialized through @Before and @BeforeClass, and 2) private static methods. They both look anti-OOP to me, and I think there is an alternative. Let me explain.

JUnit officially suggests a test fixture:

I think it's obvious what this test is doing. First, in prepare(), it creates a "test fixture" of type Folder. That is used in all three tests as an argument for the Metrics constructor. The real class being tested here is Metrics while this.folder is something we need in order to test it.

What's wrong with this test? There is one serious issue: coupling between test methods. Test methods (and all tests in general) must be perfectly isolated from each other. This means that changing one test must not affect any others. In this example, that is not the case. When I want to change the countsWords() test, I have to change the internals of before(), which will affect the other method in the test "class."

With all due respect to JUnit, the idea of creating test fixtures in @Before and @After is wrong, mostly because it encourages developers to couple test methods.

Here is how we can improve our test and isolate test methods:

Does it look better now? We're not there yet, but now our test methods are perfectly isolated. If I want to change one of them, I'm not going to affect the others because I pass all configuration parameters to a private static utility (!) method folder().

A utility method, huh? Yes, it smells.

The main issue with this design, even though it is way better than the previous one, is that it doesn't prevent code duplication between test "classes." If I need a similar test fixture of type Folder in another test case, I will have to move this static method there. Or even worse, I will have to create a utility class. Yes, there is nothing worse in object-oriented programming than utility classes.

A much better design would be to use "fake" objects instead of private static utilities. Here is how. First, we create a fake class and place it into src/main/java. This class can be used in tests and also in production code, if necessary (Fk for "fake"):

Here is how our test will look now:

What do you think? Isn't it better than what JUnit offers? Isn't it more reusable and extensible than utility methods?

To summarize, I believe scaffolding in unit testing must be done through fake objects that are shipped together with production code.