node.js - 用 Jest 模拟 nodemailer.createTransport.sendMail

标签 node.js unit-testing mocking jestjs nodemailer

我有一些使用 nodemailer 的代码模块。

在路由器(router.js)中,我有

const transporter = nodeMailer.createTransport(emailArgs);

然后在路线(/login)内我有:

...
return transporter.sendMail(mailOptions);

我正在尝试使用 jest 测试框架来测试此路线。我在模拟对 sendMail 的调用时遇到了一些问题。我读过this nice blogpost关于如何使用 Jest 模拟,但我收到此错误:

TypeError: Cannot read property 'sendMail' of undefined

事实上,当我检查 transporter 的值时,它是未定义的。

这是我的测试代码(不起作用):

import request from "supertest";
import router from "./router";

jest.mock("nodemailer");

describe("", () => {
...

    test("", async () => {
        // 1 - 200 status code; 2 - check email was sent
        expect.assertions(2);

        const response = await request(router)
            .post("/login")
            // global variable
            .send({ "email": email })
            .set("Accept", "application/json")
            .expect("Content-Type", /json/);

        // should complete successfully
        expect(response.status).toBe(200);
        // TODO not sure how to express the expect statement here
    });
});

所以我的问题是如何模拟模块返回的类实例的方法

最佳答案

我遇到了同样的问题并找到了解决方案。这是我的发现:

jest.mock("nodemailer");你告诉 jest 替换 nodemailer带有自动模拟。这意味着 nodemailer 的每个属性被替换为空的模拟函数(类似于 jest.fn() )。

这就是您收到错误 TypeError: Cannot read property 'sendMail' of undefined 的原因。 为了得到有用的东西,你必须定义 nodemailer.createTransport 的模拟函数。

在我们的例子中,我们不希望有一个具有属性 sendMail 的对象。 。我们可以用 nodemailer.createTransport.mockReturnValue({"sendMail": jest.fn()}); 来做到这一点。因为您可能想测试 sendMail被调用时,最好事先创建该模拟函数。

这是测试代码的完整示例:

import request from "supertest";
import router from "./router";

const sendMailMock = jest.fn(); // this will return undefined if .sendMail() is called

// In order to return a specific value you can use this instead
// const sendMailMock = jest.fn().mockReturnValue(/* Whatever you would expect as return value */);

jest.mock("nodemailer");

const nodemailer = require("nodemailer"); //doesn't work with import. idk why
nodemailer.createTransport.mockReturnValue({"sendMail": sendMailMock});

beforeEach( () => {
    sendMailMock.mockClear();
    nodemailer.createTransport.mockClear();
});

describe("", () => {
...

    test("", async () => {
        // 1 - 200 status code; 2 - check email was sent
        expect.assertions(2);

        const response = await request(router)
            .post("/login")
            // global variable
            .send({ "email": email })
            .set("Accept", "application/json")
            .expect("Content-Type", /json/);

        // should complete successfully
        expect(response.status).toBe(200);

        // TODO not sure how to express the expect statement here
        expect(sendMailMock).toHaveBeenCalled();
    });
});

关于node.js - 用 Jest 模拟 nodemailer.createTransport.sendMail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53420562/

相关文章:

javascript - Gulpfile.js 加载失败

node.js - 参数前置条件中的命名路由

java - JUnit 从另一个类调用一个类中的测试方法

javascript - 连接到数据库的单元测试异步函数

java - 测试包装类

javascript - 将单个 Node 插入到链表中,在下一个值处给我循环?

python - 在使用 ffmpeg 处理时流式传输 mkv 文件

python - python (2.7) unittest 的测试描述如何修改

python - 测试递归 Python 函数

python - 如何模拟数据库的方法