我正在用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”。所以我的问题是,即使service.validateUser
被成功调用了,为什么没有调用handleLoginSubmit
呢?我相信这与异步有关吗?测试Login
的身份验证功能的正确方法是什么?
答案 0 :(得分:1)
问题是您expect
所拥有的不是模拟方法。您应该期望这样的模拟方法:
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()
})