【问题标题】:Test functions that call promises inside of them with mocha使用 mocha 测试在其中调用 promise 的函数
【发布时间】:2016-05-26 11:00:16
【问题描述】:

我有一个这样的 javascript 函数:

var otherModule = require('../otherModule');

function myFn(req, res, next) {

  otherModule.queryFunction()
    .then(function(results) {
      res.json(results);
    })
    .catch(function(err)) {
      res.json({
        err: err
      });
    });
}

为了测试myFn 函数,我在单元测试中模拟了(使用mockeryotherModule.queryFunction,因此它返回了一些已知结果。在myFn 单元测试中,我想测试res.json 是否被调用。我知道如果我正在测试otherModule.queryFunction,我可以通过返回承诺或将done 参数传递给观察函数来实现。但是如果异步部分在我正在测试的函数调用的函数内,我无法弄清楚如何进行异步测试。

我尝试过这种方法但没有成功:

'use strict';
var chai = require('chai');
var mockery = require('mockery');
var expect = chai.expect;
var spies = require('chai-spies');
var myFn = require('path/to/myFn');
chai.use(spies);

describe('myFn tests', function (){

  var otherModule;
  var SOME_DATA = {data: 'hi'};
  beforeEach(function (){
    otherModule = {
      queryFunction: function queryFunctionMock(){
        var promise = new Promise(function(resolve, reject){
          resolve(SOME_DATA);
        });

        return promise;
      }
    };
  });

  beforeEach(function (){
    mockery.enable({
      warnOnReplace: false,
      useCleanCache: true
    });

    mockery.registerMock('../otherModule', otherModule);
  });

  afterEach(function (){
    mockery.disable();
  });

  it('res.json should be called with otherModule.queryFunction results', function (){
    req = chai.spy();
    res = chai.spy.object(['json']);
    next = chai.spy();

    myFn(req, res, next);

    expect(res.json).to.have.been.called();    
  });
});

【问题讨论】:

  • 如果你的myFn是异步的,它应该return一个promise。然后,您可以轻松地在测试中使用它。
  • 我不能这样做,因为 myFn 是一个快速中间件 (expressjs.com/en/guide/writing-middleware.html),它不应该返回任何东西。
  • Express 似乎并不真正关心返回值,是吗?

标签: javascript unit-testing promise mocha.js middleware


【解决方案1】:

我认为这里唯一的问题是,您需要移动被测组件的需求,初始化模拟之后:

'use strict';
var chai = require('chai');
var mockery = require('mockery');
var expect = chai.expect;
var spies = require('chai-spies');
var myFn;
chai.use(spies);

describe('myFn tests', function (){

  // [...]

  beforeEach(function (){
    mockery.enable({
      warnOnReplace: false,
      useCleanCache: true
    });

    mockery.registerMock('../otherModule', otherModule);

    // now load the component:
    myFn = require('path/to/myFn');
  });

【讨论】:

  • 感谢您的回答。即使我在启用模拟后需要 Fn,它仍然不起作用。
  • 这很奇怪。我使用您的代码创建了一个项目,但收到错误 ReferenceError: Promise is not defined,这是因为不需要 promise 库(我假设)。但这表明嘲笑是成功的。你有什么错误吗?
  • 你说得对,它有效。在将我的原始用例转换为这个示例时,我省略了一个重要的点。我在一些测试中重新定义了otherModule.queryFunction 以自定义行为。如果我想这样做,我应该注销并再次注册 de mock,因为模拟模块不是同一个实例。由于这个错误,测试从未像我预期的那样结束。
猜你喜欢
  • 2017-04-08
  • 2015-06-30
  • 2013-09-06
  • 2015-02-17
  • 1970-01-01
  • 2013-02-10
  • 2014-10-06
  • 1970-01-01
  • 2016-11-20
相关资源
最近更新 更多