【问题标题】:Capture callback result in test with mocha, sinon and node使用 mocha、sinon 和 node 在测试中捕获回调结果
【发布时间】:2013-12-31 02:37:21
【问题描述】:

我正在为我的应用程序编写一个返回回调的邮件模块:

(function() {
  "use strict";

  function Mail(opts) {
    // some sode
  }

  Mail.prototype.send = function(config, opts) {
    var transport;
    // server connect options
    config =  { ... };
    // mail body options
    opts = { ... };

    transport = nodemailer.createTransport("SMTP", config);

    transport.sendMail(opts, function(err, res) {
      if (err)
        console.error(err);
      else
        console.log('Message sent');
    });

    // transport.close();
  };

  module.exports = Mail;
}());

我的测试代码如下:

describe('smtp', function() {
  var opts, config;
  before(function() {
    config = { /* some config data */ };
    opts = { /* mail body */ }; 
    mail = new Mail();
    mail.send(config, opts);
  });
  beforeEach(function() {
    // stub console
    sandbox = sinon.sandbox.create();
    sandbox.stub(console, 'log');
    sandbox.stub(console, 'error');
  });

  afterEach(function() {
    sandbox.restore();
  });

  describe('send mail', function() {
    it('should connect and send mail', function(done) {

      sinon.assert.notCalled(console.error);
      sinon.assert.called(console.log);
      sinon.assert.calledWithExactly(console.log, 'Message sent');

      done();
    });
  });
});

邮件发送成功,但在我的测试中无法捕获返回的回调结果:

smtp
  send mail

1 failing

1) Mail smtp send mail should connect and send mail: AssertError: expected log to have been called at least once but was never called
  at Object.fail (/home/gabriel/projects-node/brim/node_modules/sinon/lib/sinon/assert.js:92:25)
  at failAssertion (/home/gabriel/projects-node/brim/node_modules/sinon/lib/sinon/assert.js:53:20)
  at Object.assert.(anonymous function) [as called] (/home/gabriel/projects-node/brim/node_modules/sinon/lib/sinon/assert.js:76:17)
  at Context.<anonymous> (/home/gabriel/projects-node/brim/test/mail.js:78:22)
  at Test.Runnable.run (/home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runnable.js:204:15)
  at Runner.runTest (/home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runner.js:378:10)
  at /home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runner.js:456:12
  at next (/home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runner.js:303:14)
  at /home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runner.js:313:7
  at next (/home/gabriel/projects-node/brim/node_modules/gulp-mocha/node_modules/mocha/lib/runner.js:251:23)

Message sent

请注意,Message sent 响应稍后会在代码运行后出现。如何改进我的测试代码?

【问题讨论】:

    标签: node.js bdd mocha.js sinon


    【解决方案1】:

    您的原始方法实际上并不是非常可测试,因为您无法真正验证何时它完成了执行。

    为此,您可能希望使用以下签名重写该方法,添加一个done 回调。

    Mail.prototype.send = function(config, opts, done) {
        var transport;
        // server connect options
        config =  { ... };
        // mail body options
        opts = { ... };
    
        transport = nodemailer.createTransport("SMTP", config);
        transport.sendMail(opts, done);
    };
    

    然后您的测试可以 create an spy 并将其作为 done 回调传递,并断言 spy 函数已被调用一次。

    【讨论】:

    • 我理解您的重构是一种在send 方法之外处理回调以获得更多控制的方法。我说的对吗?
    • 不仅如此,使用([err], other, stuff) 作为参数的done 回调是一种常见模式,就像sendMail 所做的那样,这就是为什么我可以将done 直接传递给它。遵循该模式,您可以在邮件发送后执行其他操作。
    猜你喜欢
    • 2013-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 2016-06-24
    相关资源
    最近更新 更多