我想为用React
编写的登录页面编写一个单元测试(使用Jest/Enzyme
(,我试图模拟服务器响应,这样我就可以测试登录表单是否正常工作。
我有一个React类组件,如下所示:
// LoginPage.js
export class LoginPage extends Component {
// ...
handleClick = async () => {
const username = this.state.username;
const password = this.state.password;
const result = await callServer(username, password); // "fetch" used here
console.log('Server Response:', result);
if (result) // redirect
};
render() {
return (
<Wrapper> // Styled Components
<Input type="text" id="loginUsername" ... />
<Input type="password" id="loginPassword" ... />
<Button onClick={this.handleClick}>
Submit
</Button>
</Wrapper>
)
}
}
export default withRouter(MyClass);
我的测试文件:
// LoginPage-test.js
import React from 'react';
import {configure, shallow} from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
import {LoginPage} from './LoginPage';
import Input from './Input';
import Button from './Button';
it('test the login page', async () => {
const wrapper = shallow(<LoginPage/>),
inputUsername = wrapper.find(Input).findWhere(n => n.prop('id') === 'loginUsername'),
inputPassword = wrapper.find(Input).findWhere(n => n.prop('id') === 'loginPassword'),
loginButton = wrapper.find(Button).findWhere(n => n.prop('children') === 'Submit');
inputUsername.simulate('change', { target: { name: 'loginUsername', value: 'test_user' } });
inputPassword.simulate('change', { target: { name: 'loginPassword', value: 'test_pass' } });
const result = await loginButton.props().onClick();
wrapper.update();
});
通过这个测试,我可以看到服务器响应(console.log
(和通过的测试。但我不想调用真正的服务器(因为这在测试中不是一个好的做法(,相反,我想模拟handleClick
响应。
我尝试了很多方法,spyOn
、mockImplementation
等等都没有成功。以下是我的一些尝试:
// ------------------ (1) ---------------------
jest.doMock('./LoginPage', () => {
return jest.fn().mockImplementation(() => {
return {
__esModule: true,
...(jest.requireActual(LoginPage)),
LoginPage: {
handleClick: async () => {
console.log('MOCK_TEST');
return new Promise.resolve('MOCK_TEST');
}
}
};
});
});
it('test the login page', async () => { ... });
// ------------------ (2) ---------------------
it('test the login page', async () => {
// ...
inputUsername.simulate('change', { target: { name: 'loginUsername', value: 'test_user' } });
jest.spyOn(wrapper.instance(), 'handleClick').mockImplementation(() => {
console.log('MOCK_TEST');
return 'MOCK_TEST';
});
wrapper.update();
// ...
});
// ------------------ (3) ---------------------
jest.mock(LoginPage, jest.fn());
LoginPage.mockImplementation(
() => ({
handleClick: () => {
console.log('MOCK_TEST');
return 'MOCK_TEST';
}
})
)
it('test the login page', async () => { ... });
尝试
const handleClick = jest.spyOn(LoginPage.prototype, 'handleClick).
mockImplementation(() => {
//your mock
}
和
expect(handleClick).toHaveBeenCalled();
请记住,jest.spyOn
仅适用于正常函数,而不适用于箭头函数。此外,您应该在安装测试组件之前设置spy。