How to effectively incorporate mocking into your unit tests
Mocking is an important part of unit testing components that have integrations or rely on external dependencies. But what exactly is it? In tests, mocking uses mock objects with fake business logic to replicate the function of a real object, so as isolate and focus on the code being tested without being affected by the behavior, or state, of external dependencies.
Mocks can produce better tests by reducing a factor that could cause the test to fail (e.g. needing to access an external resource like a database, which could be offline for reasons unrelated to your test) and helping you isolate the classes being tested. They can also save time and stop you from being charged for accessing these external resources.
Too much of a good thing?
Mocks are important to know how to use well, which means you have to really understand your code and its intended behavior; ideally, mocks are used only when necessary. However, new test writers sometimes go overboard, which runs the risk of slowing down tests and making them needlessly complicated. Using too many mocks can even affect whether you’re actually testing the right thing – are you testing that something is implemented in a specific way, rather than testing that the desired outcome?
Here are some best practices for mocking to help you use this method as effectively as possible.
When isn’t mocking appropriate?
Mocks work best when the code being tested isn’t tightly coupled; decoupled code tends to result from Test Driven Development (TDD), which no doubt partially explains why mocking is encouraged in the TDD community. For tightly coupled code (as is often present in legacy code), it might be the case that two or more classes form one unit, which can still be tested with a unit test. If not, think about whether the paired class has a lot of its own logic and whether it matters to test it separately. If not, don’t write a mock for it.
Similarly, don’t mock value objects; there’s simply no reason to because they don’t have their own logic. Also avoid mocking concrete classes, because these trap you in a certain implementation of the class you’re mocking.
In some cases, different types of “test doubles” similar to mocks are more appropriate instead. For a more detailed discussion about the differences between and applications for mocks, stubs, fakes, dummies, and other test doubles, check out Martin Fowler’s classic article on the topic.
Which testing framework is right for you?
Java unit testing frameworks comprise a huge collection of packages that supply pre-written code. They typically incorporate libraries, compilers, tools and APIs and give developers a consistent, clever and extensible way to build software. The one you choose will depend on a number of factors including the application and technology being tested, your testing requirements and your teams’ skills, with the most popular one being JUnit.
Which mocking framework is right for you?
You can write mocks manually, but a few open source mocking frameworks make it a lot faster and easier to maintain your mocks if you write tests frequently (which you should!).
Many mocking frameworks for Java code work in combination with JUnit and other popular unit testing frameworks, and are great depending on your specific needs. Two of the most widely used are Mockito and PowerMock. Mockito is useful for all but the most complicated cases, for which you can use PowerMock instead. Fortunately these frameworks are compatible with each other, so you can start in Mockito for most mocks and switch to PowerMock for the more complex cases.
In summary, to incorporate the best mocking practices:
- Get your unit testing techniques in shape
- Choose a testing framework
- Choose a mocking framework
But remember, less is more!
This powerful method only needs a light touch, and can help you write effective unit tests and clean, agile code. With the right tools and the careful application of these techniques, you’ll be mocking in style.
Why not try something new? Diffblue Cover autonomously writes human readable, ready to use Java unit tests so you don’t have to. Give it a go and see how much time you can save writing unit tests for Java code!