문제

I am writing a mail module for my app that returns a call back thus:

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

My test code has the following:

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

The email is sent successfully, but I can not capture the returned call back result in my test:

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

Notice the Message sent response comes later after the code has been run. How can I improve my test code?

도움이 되었습니까?

해결책

Your original method is not really very testable, as you can't really verify when it completed execution.

To that end, you might want to rewrite the method with the following signature, adding a done callback.

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);
};

Your test could then create an spy and pass that as the done callback, and assert the spy function has been called exactly once.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top