Vijay Rangan
4 min readApr 30, 2021

--

Sinon is a library that provides fakes, spies, stubs and mocks (collectively called fakes) — each of which have their place in testing. We’re going to focus on stubs in this post, covering :

  1. What stubs are
  2. How to use them to create stub objects
  3. How to stub a single function
  4. Sinon Sandbox

What is a Stub ?

So first off, what is a stub ?

Simply, a stub allows us to change and set expectations on a function or property. To quote Linus Torvalds - “Talk is cheap, show me the code”.

Say we have a module — a user repository — that’s responsible for interacting with the users table in a database.

And say we have a service that uses this module to do its job.

The user service takes an implementation of the user repository as a dependency, injected as an argument to the function. To unit test the service without actually spinning up a database (for the user repository), we need to create a stub.

Let’s look at how Sinon stubs work and how they aid in unit testing the user service module.

Digging into each of the steps above :

const stubbedUserRepo = sinon.stub(userRepo);

This creates a stub (or a programmable object) of all the methods in the userRepo object whose behaviour we can change to suit our testing needs.

With this stubbed object, we tell the all method to return a list of user objects (just one in this case) when called.

stubbedUserRepo.all.returns([{ 
id: 1,
user: "John Doe",
email: "john@doe.com"
}]);

Calling the userRepo.all() returns a list of users.

// programming the behaviour of the user repo
stubbedUserRepo.all.returns([{
id: 1,
user: "John Doe",
email: "john@doe.com"
}]);
// prints the object from above
console.log(userRepo.all());

Apart from just returning values, stubs can resolve values too for promise based interfaces. They also allows us to specify error cases by using stub.throws for instances where we’d like to fake an error. For the full list of capabilities provided by Sinon stubs, check out the link below.

Sinon stub docs : https://sinonjs.org/releases/v10.0.1/stubs/

Stubbing a single function

In some cases it may be beneficial to stub just a single method instead of an entire object. The sinon.stub function takes a second argument that specifies a the name of the function to stub.

const registerUserStub = sinon.stub(userRepository, 'registerUser');

This approach is useful if you have an object with just a few methods in it. Additionally, this approach conveys intent more explicitly.

Restoring the user repository

Say we had more tests that use this stub, we would need to restore the original userRepo object. This is because sinon mutates the original object and any tests that came after it would need to define it’s own behaviour. To restore the userRepo back to it’s original implementation :

stubbedUserRepo.all.restore();

Notice how we had to restore the method all specifically and couldn’t simply do stubberUserRepo.restore() . This approach can get cumbersome if you have an object with a lot of methods. To solve this, Sinon introduced sandboxes.

Sandbox

A sandbox, like the name suggests, creates a little playground of sorts. We can then use this sandbox to create a stub.

Notice the call to sinon.createSandbox() . This returns a sandbox instance. We can now create stubs using this sandbox.

userRepoSandbox.stub(userRepo); // instead of sinon.stub(userRepo)

Using this approach, everything can remain the same but we now have the ability to restore the object as a whole rather than using a piecemeal approach with sinon.stub(...) .

userRepoSandbox.restore();

And that’s it! It’s literally that simple to work with stubs in JavaScript using Sinon.

If you’re the kind of person that likes consuming tech content via videos, you can find a video of this on my YouTube channel.

YouTube link : Learn how stubbing works in Sinon

If you liked this article and you learned something, don’t be shy… show some love with a 👏 😀

Until next time…

--

--