node.js模拟sendmailer传输器里面的函数

我在AWS lambda中使用节点处理程序,我需要使用该function进行集成testing的另一个文件,但我不能嘲笑与sinon或嘲笑的转运。

index.js函数:

var nodemailer = require('nodemailer'); exports.handler = (event, context, callback) => { var transporter=createTransporter(); transporter.sendMail(data, function (error, success) { console.log(error); response = getResponse(404, error); } callback(null, response); }); } function createTransporter() { return nodemailer.createTransport({ service: "SMTP", auth: { user: "XXXX@XXX", pass: "XXXX" } }); } 

目的是嘲笑函数createTransporter(),以便它不发送任何电子邮件,当它在JavaScript文件testing与摩卡调用,并期望:

 var mockery = require('mockery'); var nodemailerMock = require('nodemailer-mock'); var index = require("../index.js"); describe("The handler function tests", function () { before(function () { mockery.enable({ warnOnUnregistered: false }); mockery.registerMock('nodemailer', nodemailerMock); }); it('JSON error html ', function () { var callback = function (name, response) { expect(JSON.stringify(response.statusCode)).to.be('404'); }; var context = {}; index.handler(event, context, callback); }); }); 

我写了nodemailer-mock 🙂

你遇到的问题是你正在调用var index = require("../index.js"); 在通过mockery来嘲弄nodemailer之前,它已经在模块caching中了。 我包括/ / // Make sure anything that uses nodemailer is loaded here, after it is mocked...在自述文件中的例子,但应该更清楚。

nodemailernodemailer之后移动require("../index.js") ,它将按预期工作。

 var mockery = require('mockery'); var nodemailerMock = require('nodemailer-mock'); // don't require here since you will get the real nodemailer and cache it var index; describe("The handler function tests", function () { before(function () { mockery.enable({ warnOnUnregistered: false }); mockery.registerMock('nodemailer', nodemailerMock); // do the require() here after nodemailer is mocked index = require("../index.js"); }); // your tests here should now use nodemailer-mock it('JSON error html ', function () { var callback = function (name, response) { expect(JSON.stringify(response.statusCode)).to.be('404'); }; var context = {}; index.handler(event, context, callback); }); }); 

另一个select是使用{ useCleanCache: true }选项来调用mockery.resetCache(); 尽pipe我的结果好坏参半。 请参阅在嘲笑文档中控制模块caching 。

我不是100%肯定为什么这会失败,但我build议两件事之一:

  1. 尝试做var createTransporter = function() …这里有一个细微的差别,可能是你的问题
  2. 导出createTransporter这样你就可createTransporter它分配一个新的值,不pipe是模拟的还是非模拟的。 这不是很“保持实现细节私密”,它确实有效
  3. 让你的模块返回一个或者对象,在那里你可以设置一些“使用这个传输方法”的值。 (即dependency injection)