Introduction to Unit Testing
A unit test is a test related to a single responsibility of a single class, often referred to as the System Under Test (SUT). The purpose of unit tests is to verify that the code in an SUT works. A tested object usually talks to other objects known as collaborators. These collaborators need to be created so the tested object can be assigned to them in the test. To make unit testing simpler and allow control of all aspects of the execution context, it is useful to replace the real cooperating objects with their fake replacements called test doubles. They look like the originals, but do not have any dependencies to other objects. Test doubles can also be easily programmed with specific expectations, such as recording any interactions they've had.
To make it clearer, try to imagine code for a typical en- terprise system. Now here's a service with some logic that needs two classes to fulfill its responsibility. Both classes then require a few other classes. One of these other classes could be a DAO, which needs access to a database, while yet another requires a message queue. It would be quite an effort to create that hierarchy and provide required resources. There could also be problems while running that kind of test, e.g., long startup times or the inability to test multiple developer stations simultaneously. Using Mocks, though, the same test could be much cleaner and faster.
Test doubles can be divided into a few groups1 :
- Dummy - an empty object passed in an invocation (usually only to satisfy a compiler when a method ar- gument is required)
- Fake - an object having a functional implementation, but usually in a simplified form, just to satisfy the test (e.g., an in-memory database)
- Stub - an object with hardcoded behavior suitable for a given test (or a group of tests)
- Mock - an object with the ability to a) have a programmed expected behavior, and b) verify the interactions occurring in its lifetime (this object is usually created with the help of mocking framework)
- Spy - a mock created as a proxy to an existing real object; some methods can be stubbed, while the un- stubbed ones are forwarded to the covered object
Mockito is a mocking framework helpful in creating mocks and spies in a simple and intuitive way, while at the same time providing great control of the whole process.