Jest:如何使用MongoDB正确测试Javascript服务
我完全不懂开玩笑 我有一个使用依赖注入的Jest:如何使用MongoDB正确测试Javascript服务,javascript,mongodb,testing,jestjs,Javascript,Mongodb,Testing,Jestjs,我完全不懂开玩笑 我有一个使用依赖注入的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; }
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;
}
但显然它失败了,因为select未定义
我是否也应该模拟select()
?我是否应该以不同的方式组织代码?如果要编写此测试,我将模拟使用的函数,以便在函数调用上实现期望
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
实际正在使用mock
我还将以这样一种方式构建测试,即我可以测试各种代码路径,而无需重新实现整个模拟
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)
}
}
public async getAll(){
试一试{
return wait this.userModel.find().select('name');
}捕获(e){
抛出新的HttpException(500,“获取用户时出错”。,e)
}
}
如果要编写此测试,我将模拟使用的函数,以便在函数调用上实现预期
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
实际正在使用mock
我还将以这样一种方式构建测试,即我可以测试各种代码路径,而无需重新实现整个模拟
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)
}
}
public async getAll(){
试一试{
return wait this.userModel.find().select('name');
}捕获(e){
抛出新的HttpException(500,“获取用户时出错”。,e)
}
}
是的,您应该模拟选择
。不仅如此,还包括函数内部使用的所有内容,并测试它们是否正确执行。我会这样做:
class SomeClass {
public async getAll() {
const userRecords = await this.userModel.find().select('name').catch(this.errorHandler);
return <[IUser]>userRecords;
}
public errorHandler(e) {
throw new HttpException(500, 'Error while fetching users.', e);
}
}
// this is just an example, it should be the same type as your expected returned output
const whatever = Math.random();
const fakeCatch = jest.fn(() => whatever);
const fakeSelect = jest.fn(() => {
return {
catch: fakeCatch
}
});
const fakeFind = jest.fn(() => {
return {
select: fakeSelect
};
});
const fakeUserModel = {
find: fakeFind,
}
const userService = new UserService(fakeUserModel);
const userRecords = await userService.getAll();
// should return the correct result
expect(userRecords).toEqual(whatever);
// should execute find
expect(fakeFind).toHaveBeenCalledTimes(1);
// should execute select with 'name' parameter
expect(fakeSelect).toHaveBeenCalledTimes(1);
expect(fakeSelect).toHaveBeenCalledWith('name');
// should execute catch with this.errorHandler
expect(fakeCatch).toHaveBeenCalledWith(userService.errorHandler);
class-SomeClass{
公共异步getAll(){
const userRecords=wait this.userModel.find().select('name').catch(this.errorHandler);
返回用户记录;
}
公共错误处理程序(e){
抛出新的HttpException(500,“获取用户时出错”,e);
}
}
//这只是一个示例,它应该与预期返回的输出类型相同
const whatever=Math.random();
const fakeCatch=jest.fn(()=>随便什么);
const fakeSelect=jest.fn(()=>{
返回{
捕获:伪造捕获
}
});
const fakeFind=jest.fn(()=>{
返回{
选择:fakeSelect
};
});
常量fakeUserModel={
查找:伪造查找,
}
const userService=新的userService(fakeUserModel);
const userRecords=await userService.getAll();
//应该返回正确的结果
expect(用户记录)。toEqual(无论什么);
//应该执行find
期望(伪造发现)。被催缴的时间(1);
//应使用“名称”参数执行select
期望(fakeSelect)。已被催缴时间(1);
期望(fakeSelect)。与('name')一起被调用;
//应该使用this.errorHandler执行catch
expect(fakeCatch).tohavencalledwith(userService.errorHandler);
是的,您应该模拟选择
。不仅如此,还包括函数内部使用的所有内容,并测试它们是否正确执行。我会这样做:
class SomeClass {
public async getAll() {
const userRecords = await this.userModel.find().select('name').catch(this.errorHandler);
return <[IUser]>userRecords;
}
public errorHandler(e) {
throw new HttpException(500, 'Error while fetching users.', e);
}
}
// this is just an example, it should be the same type as your expected returned output
const whatever = Math.random();
const fakeCatch = jest.fn(() => whatever);
const fakeSelect = jest.fn(() => {
return {
catch: fakeCatch
}
});
const fakeFind = jest.fn(() => {
return {
select: fakeSelect
};
});
const fakeUserModel = {
find: fakeFind,
}
const userService = new UserService(fakeUserModel);
const userRecords = await userService.getAll();
// should return the correct result
expect(userRecords).toEqual(whatever);
// should execute find
expect(fakeFind).toHaveBeenCalledTimes(1);
// should execute select with 'name' parameter
expect(fakeSelect).toHaveBeenCalledTimes(1);
expect(fakeSelect).toHaveBeenCalledWith('name');
// should execute catch with this.errorHandler
expect(fakeCatch).toHaveBeenCalledWith(userService.errorHandler);
class-SomeClass{
公共异步getAll(){
const userRecords=wait this.userModel.find().select('name').catch(this.errorHandler);
返回用户记录;
}
公共错误处理程序(e){
抛出新的HttpException(500,“获取用户时出错”,e);
}
}
//这只是一个示例,它应该与预期返回的输出类型相同
const whatever=Math.random();
const fakeCatch=jest.fn(()=>随便什么);
const fakeSelect=jest.fn(()=>{
返回{
捕获:伪造捕获
}
});
const fakeFind=jest.fn(()=>{
返回{
选择:fakeSelect
};
});
常量fakeUserModel={
查找:伪造查找,
}
const userService=新的userService(fakeUserModel);
const userRecords=await userService.getAll();
//应该返回正确的结果
expect(用户记录)。toEqual(无论什么);
//应该执行find
期望(伪造发现)。被催缴的时间(1);
//应使用“名称”参数执行select
期望(fakeSelect)。已被催缴时间(1);
期望(fakeSelect)。与('name')一起被调用;
//应该使用this.errorHandler执行catch
expect(fakeCatch).tohavencalledwith(userService.errorHandler);