单元测试:使用填充时如何模拟猫鼬代码?
Unit test: How to mock mongoose code when using populate?
我有一个带有静态函数的猫鼬模型,它通过 ID 查找员工文档并填充引用的 manager
和 interviewer
字段。
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;
});
}
我了解如何在不包含填充链时测试此函数,但填充部分让我陷入循环。
具体来说,我正在尝试测试未找到匹配记录时抛出 NotFoundError
异常,但我很困惑如何模拟 findById
方法以便 .populate()
可以在 return 值上调用。
如果我在没有 .populate()
链的情况下测试这个方法,我会做类似
let findByIdMock = sandbox.stub(Employee, 'findById');
findByIdMock.resolves(null);
return expect(Employee.findAndPopulateById('123')).to.be.rejectedWith(errors.NotFoundError);
但是当涉及填充时,这种方法当然不起作用。我想我应该 return 模拟查询或类似的东西,但我还需要能够再次调用该模拟的填充或将其解析为承诺。
如何为此代码编写测试?我的函数应该采用不同的结构吗?
好吧,这最终比我预期的要容易,我只需要在我的最终 .populate()
和 .then()
之间添加对 .exec()
的调用,以使下面的测试工作。
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);
});
我有一个带有静态函数的猫鼬模型,它通过 ID 查找员工文档并填充引用的 manager
和 interviewer
字段。
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;
});
}
我了解如何在不包含填充链时测试此函数,但填充部分让我陷入循环。
具体来说,我正在尝试测试未找到匹配记录时抛出 NotFoundError
异常,但我很困惑如何模拟 findById
方法以便 .populate()
可以在 return 值上调用。
如果我在没有 .populate()
链的情况下测试这个方法,我会做类似
let findByIdMock = sandbox.stub(Employee, 'findById');
findByIdMock.resolves(null);
return expect(Employee.findAndPopulateById('123')).to.be.rejectedWith(errors.NotFoundError);
但是当涉及填充时,这种方法当然不起作用。我想我应该 return 模拟查询或类似的东西,但我还需要能够再次调用该模拟的填充或将其解析为承诺。
如何为此代码编写测试?我的函数应该采用不同的结构吗?
好吧,这最终比我预期的要容易,我只需要在我的最终 .populate()
和 .then()
之间添加对 .exec()
的调用,以使下面的测试工作。
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);
});