ReactWrapper::state() 只能在类组件上调用 单元测试 Jest 和 Enzyme

aje*_*h s 8 unit-testing reactjs jestjs material-ui enzyme

使用笑话和酶在 React 中编写单元测试。在检查组件状态时,它会抛出错误“ReactWrapper::state()只能在类组件上调用”。

import React from 'react';
import { mount } from 'enzyme';
import expect from 'expect';
import CustomerAdd from '../CustomerAdd'
import MUITheme from '../../../../Utilities/MUITheme';
import { ThemeProvider } from '@material-ui/styles';

describe('<CustomerAdd />', () => {
    const wrapper = mount(
        <ThemeProvider theme={MUITheme}>
          <CustomerAdd {...mockProps}></CustomerAdd>
        </ThemeProvider>
        );
        test('something', () => {
            expect(wrapper.find(CustomerAdd).state('addNewOnSubmit')).toEqual(true);
        });
});
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,CustomerAdd Component 是类组件。我不知道我的代码有什么问题。任何人都可以帮我解决这个问题吗?提前致谢。

sky*_*yer 12

所以你的默认导出

export default withStyles(styles)(CustomerAdd);
Run Code Online (Sandbox Code Playgroud)

导出关于基于类的组件的功能(HOC)包装器。类名和导入是否无关紧要

import CustomerAdd from '../CustomerAdd'
Run Code Online (Sandbox Code Playgroud)

是平等的。您的测试导入包装版本,并在调用后.find(CustomerAdd)返回该 HOC 而不是您的类。并且您无法使用实例。

短时间解决方案:直接将类导出为命名导出。

export class CustomerAdd extends React.Component{
  ...
}

export default withStyles(styles)(CustomerAdd);
Run Code Online (Sandbox Code Playgroud)

在测试中使用命名导入:

import { CustomerAdd } from '../CusomerAdd';
Run Code Online (Sandbox Code Playgroud)

Quick'n'dirty 解决方案:用于.dive访问底层基于类的组件:

expect(wrapper.find(CustomerAdd).dive().state('addNewOnSubmit')).toEqual(true);
Run Code Online (Sandbox Code Playgroud)

这是相当反模式的,因为如果您在默认导出中添加任何额外的 HOC,您将需要通过添加适当数量的.dive().dive()....dive()调用来对所有相关测试进行猴子修补。

长期解决方案:避免测试状态,这是实现细节。

相反,专注于验证渲染的内容。这样,您就可以安全地应对许多不同的重构技术,例如用功能组件替换类、重命名状态/实例成员、提升状态、将组件连接到 Redux 等。