React Jest / Enzyme:模拟/覆盖ES6类方法的响应

时间:2020-07-15 19:08:24

标签: reactjs unit-testing mocking jestjs enzyme

我想用Jest/Enzyme编写登录页面的单元测试(使用React),我试图模拟服务器响应,因此我可以进行测试登录表单是否正常工作。

我有一个像这样的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响应。

我尝试了多种方法,例如使用spyOnmockImplementation等,但都没有成功。这些是我的一些尝试:

// ------------------ (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 () => { ... });

1 个答案:

答案 0 :(得分:1)

尝试

const handleClick = jest.spyOn(LoginPage.prototype, 'handleClick).
mockImplementation(() => {
    //your mock
}

expect(handleClick).toHaveBeenCalled();

请记住,jest.spyOn仅适用于普通功能,不适用于箭头功能。另外,在安装测试组件之前,您应该设置间谍。