SimpleMock is a pattern for reducing TDD damage. You can use the pattern to organize your testing code without mocking or complicated dependency injection.
SimpleMock works in any language with closures that can be passed around by reference, so off the top of my head: C#, Java, F#, Scala, PHP, C++, Ruby, and Python. I’m sure you can think of others.
- Reduced boilerplate
- Saves interfaces for real polymorphism
- Simplifies test code
- Reduces testing concerns in production code
- Removes need for fragile IoC containers
- Encourages better abstraction design
- Can convert one class at a time!
The SimpleMock pattern promotes a better design of your abstractions and simpler tests. The pattern also reduces boilerplate and the pollution of your production code with testing concerns.
If you aren’t familiar with the normal pattern of unit test mocking using interfaces, dependency injection, and mock libraries, scroll down to “The Non-SimpleMock Way” at the end of the post.
The SimpleMock pattern is aptly named.
- Replace Test-Only Interfaces With Functions
- Define Dependencies Inline
- Write Better Abstractions
Step One: Replace Test-Only Interfaces With Functions
My examples are in C# because that is what I got paid to write today – it is freshest in memory. C# has an incredible ability to create and pass around lambdas and function references. Here is an example of using functions instead of interfaces.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
The test code is quite simple! No longer do we need the dependency on third party mocking libraries, or the relatively complicated setup logic. Instead we can simply inject the lambda at runtime, replacing that pointer. We didn’t need the whole interface, really we just needed the simple signature of the function.
Step 2: Define Dependencies Inline
We can take it even a step further. Why use constructor injection at all? Since all we really want is a single mutable dispatch table row, why not just make it that way?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Now we’ve cleaned up our nasty multi-line indirection into a single dispatch line! “Go to definition” now takes me to the actual line with the actual called function! We’ve replaced a dependency on a class based interface with a function signature. The function signature is the interface!
You probably noticed we have lost something with this final version. We have lost the ability to inject polymorphic behavior through the constructor. If you need it, simply go back to injecting the interface in the constructor or by passing it into the function itself. In practice, I have found this is needed very rarely, making the SimpleMock pattern a better tool to reach for first.
Step 3: Write Better Abstractions
Lastly, SimpleMock actually promotes better designs. For example, a coworker was writing some tests today and ran into a complicated situation. Take the following sanitized code:
1 2 3 4 5 6 7 8 9 10 11
How would you check that each section was called? Our naive solution was a complicated lambda with a “timesCalled” counter and an if statement to assert against each argument, but it turns nasty quickly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Yuck! The test is an absolute catastrophe. I see a mess of mixed concerns. Conditionals?! In a test?! Unconscionable.
In situations like this, we have two easy options. Option one is to just use a third party mocking library, replacing the functions from inside the test code. This gives us access to all the sophisticated mocking tools available.
My preferred option is seeking to decomplect the production code by using better abstractions.
I have found that strong reliance of mocking libraries enables worse designs. Consider the code, what makes it so hard to test? Not knowing which element is called when, doing the same work on two parameters, and reference mutation all make this a poor abstraction. Why not simplify?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
Much better! Yes, we had to change a few signatures. We get the same work done, but now the code is actually a lot more useful. Our test code is absolutely comparable with anything you’d find using a mocking library. I am absolutely okay with using a mocking library when absolutely needed, but I always carefully consider my abstractions and design first.
If mocking libraries and IoC containers are the chainsaws of the testing world, then SimpleMock is the garden shears. Sometimes the chainsaw is absolutely the only tool for the job, and that is fine. But for most work around the yard, you can leave the chainsaw in the shed.
I’ve shown how you can really simplify your code with SimpleMock. The dispatch row is clear and easy to read. We have removed some third party mocking dependencies. You can remove a lot of the boilerplate “for making it more testable” from your code. The test code is greatly simplified, and injection a breeze. The result: much simpler code, just as easy to test.
Thanks to Shuwei Chen for helping me put this together!
The Non-SimpleMock Way
If you are familiar with unit test mocking with interfaces, this part is probably boring. Feel free to skip.
The traditional way of performing C# unit test mocking involves dependency injection and interface mocking using a mocking library. For dependency injection, it is common to use a tool like Ninject or hand-rolled constructor injection. For mocking, a library like Moq or Rhino Mocks is standard. Here is an example of a class and its testing code without any business logic.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
If you’ve done much C# unit testing, this should look familiar. We want to inject some code that is potentially long-running or dynamic. We put that code into a class, add an interface, then inject that interface into the class we want to test. To test it, we mock the interface, creating a different concrete class at test runtime which implements that interface. We can setup that mock to respond with anything, which we use for assertions.
What’s Wrong with the Non-SimpleMock Way?
The first problem is we have created a whole interface just for testing. Interfaces are for polymorphism, but we don’t really need polymorphism for this class. We simply want to mock it. The constructor injection is also test code polluting our business logic.
What we have done is create a very small and primitive dispatch table. The
table has one row: something that has a function with the signature of
() -> DateTime or, as it is known in C#:
Func<DateTime>. We will need to make
this primitive dispatch table for every single mock in every single class we
wish to test. That’s a lot of boilerplate!