单元测试:如何在使用populate时模拟mongoose代码?

时间:2017-11-13 19:58:37

标签: node.js mongoose mocha sinon chai

我有一个带有静态函数的mongoose模型,它通过ID查找员工文档,并填充引用的managerinterviewer字段。

employeeSchema.statics.findAndPopulateById = function(id) {
  return this.findById(id)
    .populate("manager", "firstname lastname email")
    .populate("interviewer", "email")
    .then(employee => {
      if (!employee) {
        throw new errors.NotFoundError();
      }
      return employee;
    });
}

我理解如何在没有包含populate链的情况下测试这个函数,但是populate部分正在抛出一个循环。

具体来说,我试图测试在找不到匹配的记录时抛出NotFoundError异常,但我很困惑如何模拟findById方法以便.populate()可以要求返回值。

如果我在没有.populate()链的情况下测试此方法,我会做类似

的操作
let findByIdMock = sandbox.stub(Employee, 'findById');
findByIdMock.resolves(null);

return expect(Employee.findAndPopulateById('123')).to.be.rejectedWith(errors.NotFoundError);

但是当涉及到填充时,这种方法当然不起作用。我想我应该返回一个模拟查询或类似的东西,但我还需要能够在该模拟上再次调用populate或将其解析为promise。

如何为此代码编写测试?我的功能应该采用不同的结构吗?

1 个答案:

答案 0 :(得分:2)

好吧,这比我预期的要容易,我只需要在.exec().populate()之间添加一个.then()的来电,让测试工作正常。

it("should throw not found exception if employee doesn't exist", () => {
  const mockQuery = {
    exec: sinon.stub().resolves(null)
  }
  mockQuery.populate = sinon.stub().returns(mockQuery);

  let findById = sandbox.stub(Employee, 'findById');
  findById.withArgs(mockId).returns(mockQuery);

  return expect(Employee.findAndPopulateById(mockId)).to.be.rejectedWith(errors.NotFoundError);
});