I am trying to mock a method's service i export as a module from my test. This is something i use to do with "sinon", but i would like to use jest as much as possible.
This is a classic test, i have an "authentication" service and a "mailer" service.
The "authentication" service can register new users, and after each new registration, it ask the mailer service to send the new user a "welcome email".
So testing the register method of my authentication service, i would like to assert (and mock) the "send" method of the mailer service.
How to do that? Here is what i tried, but it calls the original mailer.send method:
// authentication.js
const mailer = require('./mailer');
class authentication {
register() { // The method i am trying to test
// ...
mailer.send();
}
}
const authentication = new Authentication();
module.exports = authentication;
// mailer.js
class Mailer {
send() { // The method i am trying to mock
// ...
}
}
const mailer = new Mailer();
module.exports = mailer;
// authentication.test.js
const authentication = require('../../services/authentication');
describe('Service Authentication', () => {
describe('register', () => {
test('should send a welcome email', done => {
co(function* () {
try {
jest.mock('../../services/mailer');
const mailer = require('../../services/mailer');
mailer.send = jest.fn( () => { // I would like this mock to be called in authentication.register()
console.log('SEND MOCK CALLED !');
return Promise.resolve();
});
yield authentication.register(knownUser);
// expect();
done();
} catch(e) {
done(e);
}
});
});
});
});
There are two ways to mock functions: Either by creating a mock function to use in test code, or writing a manual mock to override a module dependency.
Manual mocks are defined by writing a module in a __mocks__/ subdirectory immediately adjacent to the module. For example, to mock a module called user in the models directory, create a file called user. js and put it in the models/__mocks__ directory.
In order to mock named exports in Jest, you need to import all named exports from a file with an * and assign jest. fn to the method that needs to be mocked. mockImplementation expects a callback function to be passed that describes the implementation.
To mock the static method, simply assign jest. fn() to the static method like so: Another scenario is when private constructor is used to instantiate a class (see: When to use a private constructor), the question arises — how do I mock the dependencies?
First you have to mock the mailer
module with a spy so you can later set. And you to let jest know about using a promise in your test, have a look at the docs for the two ways to do this.
const authentication = require('../../services/authentication');
const mailer = require('../../services/mailer');
jest.mock('../../services/mailer', () => ({send: jest.fn()}));
describe('Service Authentication', () => {
describe('register', () => {
test('should send a welcome email', async() => {
const p = Promise.resolve()
mailer.send.mockImplementation(() => p)
authentication.register(knownUser);
await p
expect(mailer.send).toHaveBeenCalled;
}
});
});
});
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With