我是Jest的初学者。
我使用依赖注入获得了UserService
。
public async getAll() {
const userRecords = await this.userModel.find().select('name').catch((e) => {
throw new HttpException(500, 'Error while fetching users.', e)
});
return <[IUser]>userRecords;
}
我想测试此功能。这是我可以运行的测试:
getAll
功能我认为1和2很明显,并且涵盖了不同的事物。 1覆盖请求部分,2覆盖DB部分。但是3号呢?如何“仅测试” getAll
功能?
我已经尝试过:
const userModel = {
find: (user) => {
return [
{ id: 'user1' },
{ id: 'user2' }
]
},
};
const userService = new UserService(userModel);
const userRecords = await userService.getAll();
expect(argumentRecord).toBeDefined();
但是很明显它失败了,因为select is undefined
。
我还应该嘲笑select()
吗?我应该以不同的方式组织代码吗?
如果要编写此测试,我将使用jest.fn(implementation)
模拟功能,以便可以在功能调用上实施期望。
jest.fn(implementation)
对函数调用的期望听起来似乎有些过激,但是它明确验证了const userQuery = {
select: jest.fn(() => Promise.resolve([]))
};
const userModel = {
find: jest.fn(() => userQuery)
};
const userService = new UserService(userModel);
const userRecords = await userService.getAll();
expect(userRecords).toEqual([]);
expect(userModel.find).toHaveBeenCalled();
expect(userQuery.select).toHaveBeenCalledWith('name');
确实正在使用该模拟。
我还将以这样一种方式来构造测试,使得我可以测试各种代码路径而无需重新实现整个模拟。
getAll
此代码未经测试,因此可能无法正常工作,但希望它能充分概述该想法。
虽然这与您的问题没有直接关系,但我会避免将describe('getAll()', () => {
let userQuery, userModel, userService;
beforeEach(() => {
userQuery = {
select: jest.fn(() => Promise.resolve([]))
};
userModel = {
find: jest.fn(() => userQuery)
};
userService = new UserService(userModel);
});
afterEach(() => {
expect(userModel.find).toHaveBeenCalled();
expect(userQuery.select).toHaveBeenCalledWith('name');
});
it('should get the user names', async () => {
const users = [{
name: 'john'
}, {
name: 'jane'
}];
userQuery.select.mockImplementation(() => Promise.resolve(users));
await expect(userService.getAll()).resolves.toBe(users);
});
it('should handle errors', async () => {
const error = new Error('Fake model error');
userQuery.select.mockImplementation(() => Promise.reject(error));
await expect(userService.getAll()).rejects.toMatch({
status: 500,
message: 'Error while fetching users.',
cause: error
});
});
});
与传统的承诺处理混在一起。
async/await
是,您应该模拟public async getAll() {
try {
return <[IUser]> await this.userModel.find().select('name');
} catch (e) {
throw new HttpException(500, 'Error while fetching users.', e)
}
}
。不仅如此,还可以检查函数内部使用的所有内容并测试它们是否正确执行。我会这样做:
select