Jest - 函数不调用其子异步函数
Jest - function not calling its child async function
我正在用 Jest 为我的 React Login
组件编写单元测试。该组件有一个 handleLoginSubmit
方法,在提交表单时调用该方法。这个方法其实是在我的store
里面定义的,给Login
组件传了一个引用
store.js:
handleLoginSubmit = async (event) => {
event.preventDefault();
const result = await service.validateUser(this.username, this.password);
if (result) {
this.isAuthenticated = true;
this.invalidLogin = false;
history.push('/search');
}
else this.invalidLogin = true;
}
我已经写了测试用例来检查 Login
组件在提交表单时是否调用 handleSubmit
,以及验证是否正确完成:
login.test.js
describe('Login should authenticate users corectly when', () => {
it('correct credentials are submitted', async () => {
const spySubmit = jest.spyOn(store, 'handleLoginSubmit');
const spyValidate = jest.spyOn(service, 'validateUser');
const wrapper = shallow(<Login store={store} />);
expect(spySubmit).toHaveBeenCalledTimes(0);
wrapper.find('form').simulate('submit');
expect(spySubmit).toHaveBeenCalledTimes(1);
expect(spyValidate).toBeCalledWith({ username: store.username, password: store.password });
});
});
service.js:
export function validateUser(username, password) {
return fetch(`https://abc.co/api?search=${username}`)
.then(function (response) {
return response.json();
}).then(function (response) {
if (response.results.length) {
if (response.results[0].key === password) {
return true;
}
else return false;
}
else return false;
});
}
但是测试失败并显示消息 'spyValidate was not called'。所以我的问题是,为什么 service.validateUser
没有被调用,即使 handleLoginSubmit
被成功调用?我相信这与异步有关?测试 Login
的身份验证功能的正确方法是什么?
问题是您 expect
ed 不是模拟方法。你应该期待这样的模拟方法:
expect(store.handleLoginSubmit).toHaveBeenCalledTimes(0)
与其他 expect
.
类似
在测试用例的最后,您应该通过调用 .mockRestore()
:
来恢复模拟方法
store.handleLoginSubmit.mockRestore()
如果在此之后,您仍然遇到异步调用的问题,这是我的建议,让您的测试更...单元测试:您应该将测试分成 2 个测试用例,一个用于测试是否 store.handleLoginSubmit
在表单提交后调用,另外一个是测试store.handleLoginSubmit
,
里面的内容
test('.handleLoginSubmit() called when form is submitted', () => {
jest.spyOn(store, 'handleLoginSubmit').mockImplementation(() => {})
const wrapper = shallow(<Login store={store} />);
wrapper.find('form').simulate('submit');
expect(store.handleLoginSubmit).toBeCalled()
store.handleLoginSubmit.mockRestore()
})
test('.handleLoginSubmit()', async () => {
jest.spyOn(service, 'validateUser')
.mockImplementation(() => Promise.resolve(true))
await store.handleLoginSubmit({preventDefault: () => {}})
expect(service.validateUser).toBeCalled()
service.validateUser.mockRestore()
})
我正在用 Jest 为我的 React Login
组件编写单元测试。该组件有一个 handleLoginSubmit
方法,在提交表单时调用该方法。这个方法其实是在我的store
里面定义的,给Login
组件传了一个引用
store.js:
handleLoginSubmit = async (event) => {
event.preventDefault();
const result = await service.validateUser(this.username, this.password);
if (result) {
this.isAuthenticated = true;
this.invalidLogin = false;
history.push('/search');
}
else this.invalidLogin = true;
}
我已经写了测试用例来检查 Login
组件在提交表单时是否调用 handleSubmit
,以及验证是否正确完成:
login.test.js
describe('Login should authenticate users corectly when', () => {
it('correct credentials are submitted', async () => {
const spySubmit = jest.spyOn(store, 'handleLoginSubmit');
const spyValidate = jest.spyOn(service, 'validateUser');
const wrapper = shallow(<Login store={store} />);
expect(spySubmit).toHaveBeenCalledTimes(0);
wrapper.find('form').simulate('submit');
expect(spySubmit).toHaveBeenCalledTimes(1);
expect(spyValidate).toBeCalledWith({ username: store.username, password: store.password });
});
});
service.js:
export function validateUser(username, password) {
return fetch(`https://abc.co/api?search=${username}`)
.then(function (response) {
return response.json();
}).then(function (response) {
if (response.results.length) {
if (response.results[0].key === password) {
return true;
}
else return false;
}
else return false;
});
}
但是测试失败并显示消息 'spyValidate was not called'。所以我的问题是,为什么 service.validateUser
没有被调用,即使 handleLoginSubmit
被成功调用?我相信这与异步有关?测试 Login
的身份验证功能的正确方法是什么?
问题是您 expect
ed 不是模拟方法。你应该期待这样的模拟方法:
expect(store.handleLoginSubmit).toHaveBeenCalledTimes(0)
与其他 expect
.
在测试用例的最后,您应该通过调用 .mockRestore()
:
store.handleLoginSubmit.mockRestore()
如果在此之后,您仍然遇到异步调用的问题,这是我的建议,让您的测试更...单元测试:您应该将测试分成 2 个测试用例,一个用于测试是否 store.handleLoginSubmit
在表单提交后调用,另外一个是测试store.handleLoginSubmit
,
test('.handleLoginSubmit() called when form is submitted', () => {
jest.spyOn(store, 'handleLoginSubmit').mockImplementation(() => {})
const wrapper = shallow(<Login store={store} />);
wrapper.find('form').simulate('submit');
expect(store.handleLoginSubmit).toBeCalled()
store.handleLoginSubmit.mockRestore()
})
test('.handleLoginSubmit()', async () => {
jest.spyOn(service, 'validateUser')
.mockImplementation(() => Promise.resolve(true))
await store.handleLoginSubmit({preventDefault: () => {}})
expect(service.validateUser).toBeCalled()
service.validateUser.mockRestore()
})