Better Tests Through Mocking
If you have even a moderately complex application, writing tests can be a real pain. You either wind up writing complex, fragile tests, or you skip it altogether. There is a third path: fake out all of the parts that you aren’t testing in this test. You can examine the fake parts to see what has been done with them, and you can make them respond however you want to your program.
What is a Mock?
A mock is a class that stands in for another class in a test. It’s a simplified, stripped down version you can bend to your will so you don’t have to think about it when you’re interested in testing something else.
Mocks are most easily made in object oriented languages. A mock implements the same interface as the class it will be standing in for. The difference is that rather than relying on the logic contained in that class, you explicitly tell the mock what to return in your test. This reduces dependencies in your test, and lets your write your test faster because you don’t have to do complicated setup.
When Do I Use It?
If you’re following Test Driven Development practices, you should be testing a single class in your test suite. As soon as your test touches something in an outside class, you should create a mock and inject that mock into your code in place of the actual class.
If you are doing any kind of embedded programming, where you have to interface with physical devices, mocks are essential. It isn’t practical to run your test suite on the full hardware setup when you’re test driving. Instead, you wrap classes around the interfaces to the hardware, and in your tests use a mock instead of the actual interface class.
How Do I Use Mocks?
Most modern object oriented languages have some variety of mocking framework. Java has mockito, C++ has Google Mock, PHP has PHP Unit, and you can find them for most other languages with pretensions to being object oriented.
Even if you don’t have a mocking framework, you can implement your own mock by making a descendent class of the actual class you want to mock. Override the methods which you want to use and replace them with code that will return the results you want, or record important events (e.g. method insertRecord
was called 3 times, it was given arguments Record 1, Record 2 and Record 5). You can then query your mock to see if the interactions with it were correct. For instance, you might have been expecting five interactions based on your test data, and now you’ve got to figure out where records 3 and 4 went.
Go Forth and Mock!
Now that you’ve been given a little introduction to mocking, I hope that you can start using mocks in your tests, and you’ll start writing more robust code more quickly.