What is mocking ?

Unit testing does not always rhyme with simplicity but isolating your unit of code will become one of the most useful skills in your testing journey. Find out more about how mocking works and the terminology around it.  

This article will get you started. It focuses on Javascript, and uses specifically JEST syntax, but the concepts apply to most languages and testing frameworks.

What is mocking?

Mocking is defined as the set of different types of techniques which help achieve the goal of isolating units or pieces of code in order to test them in an independent way while simulating the environment in which the unit of code exists. Mocking techniques are called test doubles and the two most common ones are Stubs and Spies (other test doubles such as dummies and fakes exist.)


Let’s take this function for example:

function isNameValid(name) {
	if (name !== "") {         	
  // some logic    

If you want to test its logic, you merely have to call the function with a non-empty string.

No mocking is needed here. You can write a test as simple as this:


Let’s now look at another function:

function foo() {
	if (Math.random() > 0.5) {
  // some logic    

If you want to test the logic within this function, you have to control the return value of Math.random (otherwise, your test would be flaky, which means it would pass sometimes and fail at other times). This is called stubbing.

Here is an example of what a test for this function could look like:

Math.random = () => 1

We have updated Math.random so it always returns 1, which to be fair is still pretty random, as illustrated in the famous meme:

Math random meme

Note that the original implementation of Math.random was never called, because it was stubbed (= replaced) instead.

Several frameworks allow you to stub easily, by taking care of implementation details for you. We’ll offer a comparison in a future article.


Here is another interesting aspect of mocking

If you remember the AAA pattern, then you know that the point of unit testing is to write assertions. But what should you assert on? By default, you can only observe what happens outside the function:

  • You can test the return value
  • You can test that parameters have been modified
  • You can test that the function took less than X milliseconds to complete
  • You can test that a global variable has been modified

However, you might also want to test some logic that happens inside the function itself.

For example, you might want to make sure the database has been queried in the following function. This is called spying:

function addUser(id) {}
// some logic   	
	db.query("INSERT INTO table VALUES ($1)", id)

In order to achieve this, you could write a unit test that looks like this:

// 1. Have a variable to store whether the database was queried
let called = false

// 2. Spy on db.query
db.query = () => { called = true }

// 3. Call our function
const result = addUser(1)‍

// 4. Assert on the return value

Observe that we respected the AAA pattern: steps 1 and 2 are Arrange, step 3 is Act, step 4 is Assert.

The fake function that we wrote at line 2 is called a spy.

Note that in practice, unlike stubs, spies don’t prevent the original function from being called. In our example above, the database will be queried in real life. If you don’t want that to happen, you might want to use both a spy and a stub.

Also note that mocks (stubs and spies) should be restored. This means resetting to the original implementation of the function. You don’t want your stubs and spies to influence other test cases that did not expect some functions to be mocked.

Here is an illustration of how restoring works with Math.random:

const originalRandom = Math.random
Math.random = () => 1
Math.random = originalRandom

Fortunately, all mocking frameworks expose nicer ways to mock and to restore functions. For example, with Jest you can just write


Why mocking?

In a typical unit test, your modules should be isolated. There should be no interactions between all the parts of your code.

You want to avoid a unit test to make API calls, rely on a database or write to your file system whenever it is run – whether from your command line or a CI. The use of mocking is the magic tool that allows your modules to be isolated.

On the contrary, you are unlikely to find mocking in integration tests.

Mocking also allows you to make assertions on side-effects of your function that could not have been tested otherwise (i.e.: how would you otherwise make sure the database was queried, if there is no database?)

When not to mock / Controversy

Mocking is a precious tool, but it’s not universally loved.

Some common reasons for disliking mocks, are that

  • Mocking undeniably increases the length of your unit tests, making them more difficult to read and to maintain.
  • It also makes your unit tests more dependent on your implementation, which means they might break even though the overall functionality of a unit doesn’t change

In particular, there are some specific scenarios where mocking is not recommended, here are a few:

1. Integration tests

The reason for this is obvious: integration tests should validate the correct interaction between different modules and parts of code as they would happen at the time of running the application. For this reason, isolation through mocking defeats the point of integration tests themselves.

2. Implementation changes

With mocking, your unit test becomes aware of the internal implementation of your function: it knows what is going to be called. This is called whitebox testing.

Say you change the implementation of addUser, and your function now calls mysql2.query instead of db.query. The unit test verifying this call will be broken.

Of course it will be easy to change, but without mocking there would have been less maintenance. Writing unit tests that are unaware of the internals of the tested functions is called blackbox testing.

Sometimes you just can’t avoid stubbing in order to run your test , but in particular in the case of spies, you should always ask yourself what makes sense to assert.

3. Testing an object subset

If you want to make an assertion on an object in which some properties are non-deterministic, it is worth considering adapting the test rather than mocking indiscriminately.

Take, for example, the scenario below.

function foo () {
	return {
  	name: "Rainbow",    
    value: Math.random(),

Two options are available to you:

  • Stub Math.random so that the object is always the same;
  • Merely test a subset of the object

You could write a test of this kind, but it would be a little verbose:

// This works but is verbose
Math.random = () => 1
expect(foo()).toEqual({ name: "Rainbow", value: 1 })

​Alternatively, you can simply use one of the following two alternatives, which achieve the same result of giving confidence in your code without the need for a stub.

// This is clean

// This is also clean
expect(foo().name).toMatchObject({ name: "Rainbow" })

How our Unit Test generation extension for VS Code helps

With Ponicode Unit Test extension, you can create mocks in one click, without learning any framework. Right click on the function you want to mock, and Tadaaa! the mocking code will be generated for you. Learn how it works with our illustrated documentation.

We have presented two common uses of mocking. It’s time for you to get started but remember: great power means great responsibilities - mocking is a great testing technique as long as it remains simple.

Do let us know what you think about it, and what your favorite tools, strategies, or libraries for mocking are. Or the worst mocking code you’ve ever seen!

Subscribe to our newsletter for more tips on mocking!

Link to the Ponicode platform

Also on the hub

Ready to write beautiful code?

Smart and simple unit testing assistant. Now available for free.

Try it now

Solutions for JS, TS, Java and Python

Lines Footer
Flexing Unicorn by Ponicode