如何使用Sinon mock sort等链式方法,解决Repository单元测试报错问题
问题原因
你当前 stub 了 EventModel.find 方法后直接返回了普通值 stubValue,但 Mongoose 的 find 方法调用后会返回一个 Query 实例,该实例才挂载了 sort、lean、exec 等链式调用方法,缺少这些方法自然会抛出 sort is undefined 报错。
可行解决方案
方案1:手动构造支持链式调用的 stub 返回值(无需额外依赖)
直接让 find 方法返回的对象挂载所有需要的链式方法,配合 sinon.stub().returnsThis() 实现链式调用的支持,最后由 exec 方法返回你需要的模拟数据即可。
修改后的单元测试代码如下:
describe("getEvents", () => { it("should retrieve all events", async () => { // 先定义你要返回的模拟数据 const mockEvents = [{ _id: 'testId', createdAt: new Date('2024-01-01'), // 补充其他需要的 EventDocument 字段 }] // stub find 方法,返回支持链式调用的对象 const findStub = sinon.stub(EventModel, "find").returns({ sort: sinon.stub().returnsThis(), lean: sinon.stub().returnsThis(), exec: sinon.stub().resolves(mockEvents) }) const result = await eventRepository.findEventsByTriggerDate(testDate); expect(findStub.calledOnce).to.be.true; // 注意原方法返回的是数组,需要取对应位置的元素再断言 expect(result[0].createdAt).to.equal(mockEvents[0].createdAt); // 测试完成后恢复 stub 避免影响其他用例 findStub.restore() }); });
说明
returnsThis()会让 stub 方法返回当前对象,完美适配链式调用场景,哪怕后续你调整了sort、lean的调用顺序也不需要修改 stub 逻辑- 不要忘记测试完成后调用
restore()恢复原方法,避免污染其他测试用例
方案2:使用 sinon-mongoose 工具库(适合大量 Mongoose 测试场景)
如果你的项目有大量需要测试 Mongoose 查询的场景,可以引入 sinon-mongoose 扩展,它内置了对 Query 所有链式方法的 stub 支持,无需手动逐个定义。
额外注意
你原测试代码中直接断言 result.createdAt 是错误的,因为 Repository 层的 findEventsByTriggerDate 方法返回的是 EventDocument[] 数组,需要先取出数组中的对应元素再做字段断言。
内容的提问来源于stack exchange,提问作者iranichai
相关产品推荐
相关产品推荐

