What and why mocks?
Last updated
Last updated
There are usually objects dependencies in the code base of software projects, whether for a simple or a complex project.
This is because the various objects need to interact and share information across boundaries.
However, to effectively unit test the objects and isolate their behaviors, each object must be tested in isolation, irrespective of the dependencies it has on other objects
In order to achieve this, the dependent objects in a class are replaced with mocks to allow the object being tested to be effective when tested in isolation,
Mocks allows us to do this without having to go through the pain of constructing the dependent objects, which sometimes might not be fully implemented or may be impractical to construct at the time the object being tested is written
In a well-architected software system, there are usually objects that interact and coordinate to accomplish set objectives based on the business or automation requirements.
Quite often, these objects are complex and rely on other external components or systems, such as databases, SOAP, or REST services for data and internal state updates.
Making use of these services for every test run is expensive and time consuming.
The main characteristics of a unit test are that it should run very quickly and should give consistent results even when executed multiple times with the same set of data
The benefits of unit testing can be lost when you have long running tests that apparently waste productive time
When we have the dependencies isolated, you can focus on the test being run, thereby limiting the scope of your test to the code that really matters for the test.
In essence, with the reduced scope, we can easily refactor the code being tested as well as the test itself, giving us a clear picture of areas where the code can be improved
Legacy source code is the code that was written by you or someone else usually without tests or using an old framework, architecture, or technology. Such a code base can be difficult to rewrite or maintain.
When faced with the daunting task of maintaining a legacy code base, especially a code base written without adequate or proper testing, writing unit tests for such code can be difficult, and a waste of time, and can result in a lot of hard work.
However, using a mocking framework can greatly simplify the refactoring process, as the new code being written can be isolated from the existing code and tested using mock objects.
With mocks, you are sure of a wide test coverage, as you can easily use mock objects to simulate possible exceptions, execution scenarios, and conditions that otherwise would be difficult without mocks.
For example, if you have a method that purges or drops a database table, it is safer to test this method using mock objects than run it on a live database each time the unit test is run!
Gerard Meszaros uses the term Test Double as the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined five particular kinds of double:
Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
Here is one interesting blog on this.