макет nodemailer.createTransport.sendMail с шуткой - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть код, который использует модуль nodemailer .

В маршрутизаторе (router.js) у меня есть

const transporter = nodeMailer.createTransport(emailArgs);

Затем внутри маршрута (/login) У меня есть:

...
return transporter.sendMail(mailOptions);

Я пытаюсь протестировать этот маршрут с использованием jest инфраструктуры тестирования.У меня возникли проблемы с издеванием над sendMail.Я прочитал этот хороший пост о том, как использовать шутки, но я получаю эту ошибку:

TypeError: Невозможно прочитать свойство 'sendMail' из неопределенного

И действительно, когда я проверяю значение 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
    });
});

Так что мой вопрос как мне смоделировать метод экземпляра класса, который возвращается модулем ?

1 Ответ

0 голосов
/ 29 января 2019

Я столкнулся с той же проблемой и нашел решение.Вот что я обнаружил:

С 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();
    });
});
...