【问题标题】:Sinon stub not called after promise returned承诺返回后未调用 Sinon 存根
【发布时间】:2018-03-29 17:28:30
【问题描述】:

我正在尝试使用 Mocha、Chai 和 Sinon 向我的代码添加更多测试,但是我很难理解为什么第二个存根函数未被识别为被调用。

我有一个向用户发送电子邮件的功能(稍后我将测试电子邮件功能 - 现在我只想处理我控制的存根依赖项)

// EmailSender.js
const models = require('../models');
const User = models.user;
const emailLogger = require('./emailLogger');

class EmailSender {
  constructor(subject, emailData) {
    this.subject = subject;
    this.emailData = emailData;
  }

  sendToUser() {
    let email = this.emailData.email;

    User.findOne({ where: { $or: [
      { email: email },
      { workEmail: email },
    ] } })
    .then(function (userData) {
      if (userData) {
        emailLogger.log('Send to anon - sending to user ' + userData.id);
      });
    } else {
      emailLogger.log('Send to anon - no user found');
    }
  }
}

还有一个测试文件:

const EmailSender = require('../../../helpers/emailSender');
const models = require('../../../models');
const User = models.user;
const emailLogger = require('../../../helpers/emailLogger');
const chai = require("chai");
const sinon = require('sinon');
const sinonChai = require("sinon-chai");

const expect = chai.expect;
chai.use(sinonChai);

describe('The emailSender', () => {
  let emailData;

  beforeEach(() => {
    emailData = {
      email: 'testemail@eml.co'
    };
    sinon.stub(User, 'findOne').returns(Promise.resolve());
    sinon.stub(emailLogger, 'log');
  })

  afterEach(() => {
    User.findOne.restore();
    emailLogger.log.restore();
  })

  describe('sendToUser method', () => {
    it('logs an email if a user is found', () => {
      let emailSender = new EmailSender('Email subject', emailData);
      emailSender.sendToUser();

      expect(User.findOne).to.have.been.calledOnce; // works
      expect(emailLogger.log).to.have.been.calledOnce; // doesn't
    })
  })
});

我可以用 Sinon 存根 User.findOne() 方法,但是当我尝试存根 emailLogger.log() 方法时,我遇到了麻烦。它似乎调用了存根而不是真正的方法,但 expect(emailLogger.log).to.have.been.calledOnce 返回 false。

我尝试添加done() 和一个假计时器以防出现延迟问题,以及一系列其他事情,但到目前为止没有运气。

【问题讨论】:

    标签: javascript node.js unit-testing mocha.js sinon


    【解决方案1】:

    一个很好的技巧是从测试函数返回承诺,这会导致 Mocha 等到承诺完成。这样做的方法如下:

    it('logs an email if a user is found', () => {
       const emailSender = new EmailSender('Email subject', emailData);
       return emailSender.sendToUser().then( () => {  
          //check after the sendToUser promise is complete, but before the test is done  
          expect(User.findOne).to.have.been.calledOnce; 
          expect(emailLogger.log).to.have.been.calledOnce; 
       });
     });
    

    这有一个额外的好处,即如果承诺因任何原因失败,测试将失败(出现正确的错误)。

    【讨论】:

      【解决方案2】:

      您永远不会从 sendToUser 函数返回承诺,这意味着无法知道它何时真正完成。当您以同步方式测试async 函数时,这意味着您要询问emailLogger.log 是否已被调用,之前它在代码中被调用!

      你需要回报承诺,然后你就可以按照邓肯在他的回答中提出的建议去做。

      【讨论】:

        猜你喜欢
        • 2017-05-21
        • 2015-11-28
        • 2016-06-15
        • 2020-05-23
        • 1970-01-01
        • 1970-01-01
        • 2016-09-26
        • 1970-01-01
        • 2018-06-10
        相关资源
        最近更新 更多