简体   繁体   English

用 Jest 模拟 nodemailer

[英]Mocking nodemailer with Jest

I setup an endpoint which allows the user to reset their password.我设置了一个端点,允许用户重置他们的密码。 Everything works and the tests were passing UNTIL I added nodemailer and included a line which sends the user an email.一切正常,测试通过,直到我添加了 nodemailer 并包含一行向用户发送电子邮件。

I am using Jest for my tests.我正在使用 Jest 进行测试。

If I comment out the line which sends the emails the tests pass, mailer.sendPasswordResetEmail(body.email, token);如果我注释掉发送测试通过的电子邮件的行, mailer.sendPasswordResetEmail(body.email, token); if I leave the line in - my tests fail.如果我离开线路 - 我的测试失败。 I have confirmed with REST client that everything is working properly which leads me to believe the test is the issue.我已经与 REST 客户端确认一切正常,这让我相信测试是问题所在。

ReferenceError: You are trying to import a file after the Jest environment has been torn down. ReferenceError: 您正在尝试在 Jest 环境被拆除后导入文件。

test("if a valid user requests a password change, they should be assigned a hash", async () => {
    const userBefore = await helper.getUser();

    expect(userBefore.passwordResetHash).toBe("");

    await api
      .post("/api/reset-password")
      .send({ email: userBefore.email })
      .expect(200);

    const userAfter = await helper.getUser();

    expect(userAfter.passwordResetHash).not.toBeNull();
  });

I think that I am not mocking nodemailer properly - does anyone have any experience using nodemailer and jest together?我认为我没有正确地嘲笑 nodemailer - 有没有人有一起使用 nodemailer 和 jest 的经验? or is there a better way to do it或者有更好的方法来做到这一点

The files in question are controllers/resetPassword.js , utils/mailer.js and tests/resetPassword.test.js .有问题的文件是controllers/resetPassword.jsutils/mailer.jstests/resetPassword.test.js

controllers/resetPassword.js控制器/重置密码.js

resetPasswordRouter.post("/", async (request, response) => {
  // get email from request
  const { body } = request;

  // get the user with matching email
  const user = await User.findOne({ email: body.email });

  // if not found return error
  if (!user) {
    return response.status(400).json({ error: "User not found" });
  }

  // if user generate a token
  const token = helper.generateToken();

  // create a new user object with the resetPasswordHash defined
  const update = {
    passwordResetHash: await bcrypt.hash(token, 10),
  };

  // update user model with the password hash
  const updatedUser = await User.findByIdAndUpdate(user.id, update, {
    new: true,
  });

  mailer.sendPasswordResetEmail(body.email, token);

  // setup timer to reset password hash in 30 minutes
  setTimeout(async () => {
    await User.findByIdAndUpdate(
      user.id,
      { passwordResetHash: "" },
      { new: true }
    );
  }, 30000); // half hour

  // return the updated user with the hash set
  response.status(200).json(updatedUser);
});

utils/mailer.js实用程序/mailer.js

const nodemailer = require("nodemailer");
const config = require("../utils/config");

const mailer = nodemailer.createTransport({
  host: "smtp.mailtrap.io",
  port: 1111,
  auth: {
    user: "8b4f30425e75ea",
    pass: "8b4f30425e75ea",
  },
});

const sendPasswordResetEmail = (email, token) => {
  const sitename = config.SITENAME;
  const resetPasswordLink = `${sitename}/api/reset-password/verify?email=${email}&token=${token}`;

  mailer.sendMail({
    to: email,
    from: config.FROM_EMAIL,
    subject: `Password Reset | ${sitename}`,
    html: `<h1>Password Reset</h1>
           <p>Hello, you\'ve requested a password reset.</p>
           <p><a href="${resetPasswordLink}">Click here to reset your password</a>, if you did not make this request please disregard the email.</p>`,
  });
};

module.exports = {
  sendPasswordResetEmail,
};

You can find the repository here: https://github.com/gerrgg/gregpress您可以在此处找到存储库: https : //github.com/gerrgg/gregpress

ReferenceError: 您正在尝试在 Jest 环境被拆除后导入文件。

You need to mock the function mailer.sendPasswordResetEmail so when the controller calls it, it'll actually call your mock implementation.您需要模拟函数mailer.sendPasswordResetEmail以便当控制器调用它时,它实际上会调用您的模拟实现。

test("if a valid user requests a password change, they should be assigned a hash", async () => {
    const userBefore = await helper.getUser();

    expect(userBefore.passwordResetHash).toBe("");

    // Jest spy to intercept mailer.sendPasswordResetEmail call
    let spy = jest.spyOn(mailer, 'sendPasswordResetEmail').mockImplementation(() => return true);

    await api
      .post("/api/reset-password")
      .send({ email: userBefore.email })
      .expect(200);

    const userAfter = await helper.getUser();

    expect(userAfter.passwordResetHash).not.toBeNull();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM