Mocking, Stubbing, and Test Isolation

Rayhan Arwindra
Pilar 2020
Published in
4 min readOct 22, 2020
Source: https://www.freepik.com/vectors/people People vector created by pch.vector — www.freepik.com

It is not uncommon for a certain class, function, or component to depend on external functionalities to make them work. For example, a class in Java might call a function from another class, or the fronted of an application would fetch a get request from a backend API.

This creates a problem for testing, as we cannot fully determine whether the tests fail because of bugs in the current component we’re testing, or it’s because of faults on external components that it is dependent upon.

To counter this issue, we need to make sure that our test is isolated, so that we can pinpoint the issue if a certain test fails. This also improves the performance of your tests, as connecting your tests to an API, database, or other external dependencies takes time to do so.

We can achieve test isolation by the use of “fakes”, which we will discuss further below.

Fake Objects

Fake objects are interpretations of a certain object, for example an external dependency. These fakes have working implementations of the actual object, but is simplified for quicker and lighter use.

When used in tests, fakes can simulate the functionality of an external dependency of the object we’re currently testing, without actually calling or loading in said dependency.

There are two types of fake objects in testing: mocks, and stubs.

Mocking vs Stubbing

Mocks and stubs are both examples of fakes, meaning that they can act as an implementation of an external service or dependency. However, there are a couple of differences between the two.

Mocks

To create a mock object means that we are making a fake version of the external dependency which can act as a replacement for the real object required. By using mocks, we can make our tests run faster, and the result of the test becomes more reliable.

We can use mocks if we don’t wish to call code in production, or if we have difficulty in verifying or asserting if a code is correct or not when using an external service.

For example, let’s say we wish to test a function that creates a new object in a database. Instead of spamming the database with new objects every time we test, we can simply use a mock object to test the function.

Stubs

Stubs are similar to mocks, in that they also create an implementation for an external service in a test. However, unlike mocks, stubs only create a replica of the behavior of the object, not the entire object itself.

Stubs are useful if the object you are trying to test only needs a particular behavior of an object, but does not require the whole object.

Mocking Example

Source: Pilar Project code snippet

Above is an example of a functional test for a React.js project using the Jest testing library.

Here, the component DetailBatch requires data received from a backend API. Instead of actually requesting the data from the backend, we instead create a mock response, which is an implementation of the data to be received.

After mocking the received data, we can assert if the data received is correct, and verify if this component’s functionality is correct or not.

Other than the advantage of the tests running quicker, and the ability to easily verify the correctness of this component, I find that using mocks when testing helps me to verify my component’s correctness when the backend implementation hasn’t been made yet.

This is because I don’t need to wait idly for the backend API service required for this component in order to test it. Instead, by using mock, I can create an imitation of the service, thereby verifying whether or not the component I made has the correct functionality or not.

Stubbing Example

Given the class Student.java below:

Let’s say we are trying to make a test for the function inLecture().

To do so while maintaining test isolation, we can create a stub as follows:

The StubLecture class acts as an implementation of the Lecture class. By doing this, we can get the behavior of the Lecture class without actually creating the Lecture object itself.

Conclusion

While test isolation is not a must, it’s undeniable that the benefits of doing so far outweigh the effort. Using fake objects such as mocks and stubs are among the best ways of ensuring that your tests are isolated from external dependencies.

Using mocks and stubs in your tests ensures that your test runs quickly, and is independent of external services. Even if your object requires external dependencies, it’s still important to test them independently to make sure that the results of your test are reliable.

--

--