Article thumbnail

Understanding mocks in testing



What mocks are? If you are curious you need to read this article. We'll check different kinds of mocks and we'll use them in practice.


During the earlier lesson, we learned the stubs and realized what they are used for. Now is the time for mocks, which are used very often during unit testing.

Mocks definition

Mocks are used to replace the implementation of a specific module. Their main objective is to provide:

  • Isolation - you can define the expected behavior of the mock and specify the responses
  • Control - they can simulate different scenarios and edge cases that may be challenging to reproduce with real dependencies
  • Simplicity - they eliminate the need for complex setups or configurations that may be required for using real dependencies
  • Performance - mocks can be faster and more efficient than using real dependencies
  • Testing unavailable or unreliable modules - by mocking module which is broken you can test the behavior of your code

Why are mocks so important?

Think of a situation where you make a query to a mailing service in the code that you are testing. If you don't mock the API of that service then you're making real queries.

It would cost you a bit 💰.

Why do we need to use mocks?

Let's say we have the following function that is designed to build a path for specific article:


What catches the eye immediately is the use of the path module and the globally available process variable.

The path module is not a part of our application, but an external library - we assume that it works properly, we don't want to test it.

The process variable is an object created by the NodeJS runtime environment. It has properties and methods. Also, we have to assume that it works correctly and we don't want to test it.

How should we test it? We need to mock both and simulate the behavior of the cmd() and join() methods. We know how they work so it won't be a problem.

Let's mock

This is how the join() and cwd() methods work:


Now all we need to do is create a test in which we substitute their implementation and check whether our own function works as expected.


In the first mock we replace the implementation of the path module and the join method. Thanks to the jest.fn() we will be able to change the implementation in any other test as needed.


In the second one, we used defineProperty to override a globally available process object property.


It is very important to assign a starting value to global objects after testing. If we don't do this, we expose ourselves to side effects and the fact that tests in this file can affect other tests - which is very bad!

Note the use of the object descriptor (writeable: true), which allowed us to restore to the initial value later. Without this change, it is not possible to overwrite the cwd property implementation.


Bravo! Now you know how important mocks are and how to create them for modules, methods and global objects. You have to admit that their use is much wider than in the case of stubs.

If you enjoyed it, be sure to visit us on Linkedin where we regularly upload content from programming.

I create content regularly!

I hope you found my post interesting. If so, maybe you'll take a peek at my LinkedIn, where I publish posts daily.


Add your honest opinion about this article and help us improve the content.

created: 10-04-2023
updated: 10-05-2023