Reputation: 828
Within an ExpresS API I'm using the Postmark library to send an email, which is initiated like this:
var postmark = require("postmark");
var client = new postmark.Client("aaaa-bbbbb-cccc");
And then used to send a password reset mail later on with:
client.sendEmailWithTemplate(
// Options here
);
Now, I would like to test this function has been called, but I have difficulties finding out how to mock/spy on this.
I have tried the following (simplified):
const request = require("supertest");
const app = require("../server/app");
const postmark = require("postmark");
jest.mock("postmark");
describe("API Tests", () => {
test("it should give a reset link when requesting with existing e-mail address", () => {
return request(app)
.post("/api/auth/passwordreset")
.send({
email: "[email protected]"
})
.then(response => {
expect(postmark.Client).toHaveBeenCalled();
});
});
});
This works, but it's only testing if postmark has been used, since I can't figure out how to actually test the client.sendEmailWithTemplate
method
Any suggestions on how to accomplish this?
EDIT: following up on @samanime answer I created a repo to illustrate the 'challenge'
https://github.com/Hyra/jest_test_example
Upvotes: 1
Views: 1896
Reputation: 26547
You can specifically mock out the Client
function that is returned by the mocked postmark
to return an object with mocked functions.
In Jest, you can provide specific mocking code for a node_modules
by creating a folder named __mocks__
at the same level as node_modules
, i.e.,
/project-root
/node_modules
/__mocks__
Note, that is two underscores on each side.
In there, make a function named <package_name>.js
(in your case, postmark.js
). It will then load whatever is exported by that when you use the mock
.
In that file, you can mock it out as needed. Something like this would probably work:
// global jest
module.exports = {
Client: jest.fn(() => ({
sendEmailWithTemplate: jest.fn(() => {})
}))
};
It doesn't have to be as compact as this, but basically it makes postmark
have a function called Client
which returns an object that has a functiono called sendEmailWithTemplate
, both of which are mocks/spys.
Then you can just check if postmark.Client.sendEmailWithTemplate
was called.
The one gotcha is you'll need to be sure to reset all of these in between tests. You could do this manually in your beforeEach()
, but if you are going to reuse it, I like to add an extra function named __reset()
which will reset the code and just call that:
// global jest
const mockedPostmark = {
Client: jest.fn(() => ({
sendEmailWithTemplate: jest.fn(() => {})
}))
};
mockedPostmark.__reset = () => {
mockedPostmark.Client.mockClear();
mockedPostmark.Client.sendEmailWithTemplate.mockClear();
};
module.exports = mockedPostmark;
You can add additional functions as needed as well.
Upvotes: 1