您好我试图在Jest中为我编写的模块编写一些单元测试,但目前有些困难,需要一些建议如何继续。
export const submitOrder = async (body, key) => {
const clientRepo = new ClientRepository(db)
const companyRepo = new CompanyRepository(db)
const company = await getCompanyByKey(
companyRepo,
key
);
const client = await createClient(
clientRepo,
body
);
await addClientToCompany(
companyRepo,
client.id,
company.id
);
.. More things
}
我可以通过传递模拟的存储库轻松测试每个函数(getCompanyByKey
,createClient
和addClientToCompany
)。
但我也想测试我的"流程"通过检查我的存储库函数是否已被调用,submitOrder
函数。但是我需要每个存储库的实例,在我的submitOrder
函数之前我不会实例化。
像这样的东西,这与我对我的功能进行单元测试的方式类似。
jest.mock('../repositories/ClientRepository');
jest.mock('../repositories/CompanyRepository');
test('should be able to submit an order', async () => {
const apiKey = 'mocked-super-key';
const body = getMockData();
const result = await submitOrder(body, apiKey);
expect(result).toMatchSnapshot();
expect(CompanyRepository.findByKey).toHaveBeenCalled();
expect(ClientRepository.create).toHaveBeenCalled();
expect(CompanyRepository.addClient).toHaveBeenCalled();
});
您是否有任何关于如何测试我的存储库是否已被调用的提示?
答案 0 :(得分:1)
您描述的问题是依赖注入背后的激励因素之一。
作为一个示例:您的submitOrder()
代码使用new
直接实例化特定实现ClientRepository
的客户端存储库。相反,它可以声明它具有依赖性 - 它需要一个实现客户端存储库接口的对象。然后它可以允许这样的对象由周围环境提供("依赖注入容器"在流行语中)。然后在测试期间,您将创建并提供(" inject")模拟实现,而不是真正的实现。
如果您必须能够在多个"真实"之间进行选择,这还有一个额外的好处。实施,您已经设置了这样做。
有很多方法可以实现这一目标。它可以像设计模式一样简单,或者对于更完整的解决方案,您可以使用依赖注入框架。
如果你绝对无法为这种做法重构你的代码,那么JavaScript足够动态,你可以拼凑一种方法拦截new
的调用,从而模拟依赖注入。
答案 1 :(得分:1)
您可以将模拟实现工厂作为第二个参数传递给jest.mock
,as described in the docs。
您可以使用它来模拟您要检查的方法。
试试这个:
jest.mock('../repositories/CompanyRepository', () => {
findByKey: jest.fn(),
addClient: jest.jn()
});
const mockCreate = jest.fn();
jest.mock('../repositories/CompanyRepository', () => class {
create(...args) {
mockCreate(...args);
}
});
test('should be able to submit an order', async () => {
const apiKey = 'mocked-super-key';
const body = getMockData();
const result = await submitOrder(body, apiKey);
expect(result).toMatchSnapshot();
expect(CompanyRepository.findByKey).toHaveBeenCalled();
expect(ClientRepository.create).toHaveBeenCalled();
expect(CompanyRepository.addClient).toHaveBeenCalled();
});
由于 CompanyRepository 是使用“new”创建的,因此我们在这种情况下使用类定义并传入一个调用“create”方法时调用的mock函数。