如何正确测试将Mongoose查询作为Promises返回的函数

时间:2017-08-03 04:24:10

标签: unit-testing mongoose mocha sinon chai

我正在尝试编写一个基本的单元测试来处理下面的函数,但无法使其工作。如何测试返回正确的npm-express响应?

我已经查看了Using Sinon to stub chained Mongoose callshttps://codeutopia.net/blog/2016/06/10/mongoose-models-and-unit-tests-the-definitive-guide/Unit Test with Mongoose,但仍然无法弄明白。我当前的最佳猜测以及由此产生的错误低于要测试的功能。如果可能的话,我不想使用任何东西,除了Mocha,Sinon和Chai.expect(即不是sinon-mongoose,chai-as-expected等)。任何其他建议,比如我可以/应该在这里测试的其他建议,是受欢迎的。谢谢!

要测试的功能:

function testGetOneProfile(user_id, res) {
  Profiles
    .findOne(user_id)
    .exec()
    .then( (profile) =>  {
      let name   = profile.user_name,
        skills = profile.skills.join('\n'),
        data   = { 'name': name, 'skills': skills };
      return res
        .status(200)
        .send(data);
    })
    .catch( (err) => console.log('Error:', err));
}

我目前的最佳猜测单元测试:

const mongoose = require('mongoose'),
      sinon    = require('sinon'),
      chai     = require('chai'),
      expect   = chai.expect,
      Profile  = require('../models/profileModel'),
      foo      = require('../bin/foo');

mongoose.Promise = global.Promise;

describe('testGetOneProfile', function() {
  beforeEach( function() {
    sinon.stub(Profile, 'findOne');
  });
  afterEach( function() {
    Profile.findOne.restore();
  });

  it('should send a response', function() {
    let mock_user_id = 'U5YEHNYBS';
    let expectedModel = {
      user_id: 'U5YEHNYBS',
      user_name: 'gus',
      skills: [ 'JavaScript', 'Node.js', 'Java', 'Fitness', 'Riding', 'backend']
    };
    let expectedResponse = {
      'name': 'gus',
      'skills': 'JavaScript, Node.js, Java, Fitness, Riding, backend'
    };
    let res = {
      send: sinon.stub(),
      status: sinon.stub()
    };
    sinon.stub(mongoose.Query.prototype, 'exec').yields(null, expectedResponse);
    Profile.findOne.returns(expectedModel);

    foo.testGetOneProfile(mock_user_id, res);

    sinon.assert.calledWith(res.send, expectedResponse);
  });
});

测试信息:

  1) testGetOneProfile should send a response:
     TypeError: Profiles.findOne(...).exec is not a function
      at Object.testGetOneProfile (bin\foo.js:187:10)
      at Context.<anonymous> (test\foo.test.js:99:12)

1 个答案:

答案 0 :(得分:3)

这是一个棘手的场景。这里的问题是测试中的findOne存根返回模型对象 - 相反,它需要返回一个包含属性exec的对象,而属性const findOneResult = { exec: sinon.stub().resolves(expectedModel) } Profile.findOne.returns(findOneResult); 又是一个最终解析为模型值的promise-returns函数。 ..是的,如上所述,它有点棘手:)

这样的事情:

status

您还需要让响应对象上的send函数返回包含//if we set up the stub to return the res object //it returns the necessary func res.status.returns(res); 函数的对象

{{1}}

我认为你不应该在测试中改变任何其他东西,它可能会那样工作。请注意,你可以使用sinon 2.0或更新版本来解析函数存在于存根(或者你可以使用sinon-as-promised with sinon 1.x)

这篇文章详细介绍了如何处理这样的复杂对象: https://codeutopia.net/blog/2016/05/23/sinon-js-quick-tip-how-to-stubmock-complex-objects-such-as-dom-objects/