单元测试:使用填充时如何模拟猫鼬代码?

Posted

技术标签:

【中文标题】单元测试:使用填充时如何模拟猫鼬代码?【英文标题】:Unit test: How to mock mongoose code when using populate? 【发布时间】:2018-04-26 14:50:55 【问题描述】:

我有一个带有静态函数的猫鼬模型,它通过 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;
    );

我知道当这个函数不包含填充链时如何测试它,但是填充部分让我陷入了循环。

具体来说,我正在尝试测试在找不到匹配记录时是否会引发NotFoundError 异常,但我很困惑如何模拟findById 方法以便可以在返回值上调用.populate()

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

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

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

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

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

【问题讨论】:

【参考方案1】:

好吧,这最终比我预期的要容易,我只需要在我的最终 .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);
);

【讨论】:

以上是关于单元测试:使用填充时如何模拟猫鼬代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mocha 单元测试中使用猫鼬?

模拟 API 响应时如何在单元测试中使用 JSON 文件

如何在 Service 构造函数中对 Controller 进行单元测试和模拟 @InjectModel

在模拟API响应时,如何在单元测试中使用JSON文件

Mockgoose:如何模拟猫鼬中的错误?

在对 Knex 进行单元测试时,如何模拟假数据库?