【问题标题】:ReactWrapper::state() can only be called on class components Unit Testing Jest and EnzymeReactWrapper::state() 只能在类组件单元测试 Jest 和 Enzyme 上调用
【发布时间】:2020-02-14 05:00:24
【问题描述】:

使用 jest 和酶编写反应单元测试。在检查组件状态时,它会抛出错误“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);
        });
});

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

【问题讨论】:

  • 很难确定。检查您的导入/导出。我的意思是默认导出可以是基于类的组件的包装,而您需要使用命名导出。 PS无论如何,你最好不要反对state(),测试变得脆弱。
  • 我认为在基于类的组件中使用用作包装器的功能组件时会出现问题。有什么解决办法吗?
  • 如何声明的?
  • ThemeProvider 是 Material ui ThemeProvider 组件。它是一个功能组件。如果我从 CustomerAdd 中删除这个和相应的依赖项。它工作正常。但我需要带有 ThemeProvider 的 CustomerAdd
  • '../CustomerAdd' 的默认导出是什么样的?

标签: reactjs unit-testing jestjs material-ui enzyme


【解决方案1】:

所以你的默认导出

export default withStyles(styles)(CustomerAdd);

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

import CustomerAdd from '../CustomerAdd'

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

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

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

export default withStyles(styles)(CustomerAdd);

在测试中使用命名导入:

import { CustomerAdd } from '../CusomerAdd';

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

expect(wrapper.find(CustomerAdd).dive().state('addNewOnSubmit')).toEqual(true);

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

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

而是专注于验证渲染的内容。然后,在许多不同的重构技术(例如用功能组件替换类、重命名状态/实例成员、提升状态、将组件连接到 Redux 等)的情况下,您是安全的。

【讨论】:

  • expect(wrapper.find('CustomerAdd').state('addNewOnSubmit')).toEqual(true);这对我有用:)
  • 很好,但这是一种最棘手的方式,因为您依赖于 React 本身基于类名称隐式设置的 displayName。假设你用 const CustomerAdd = function ... 之类的功能组件替换类,使用命名导入的方法仍然有效,而 find('CustomerAdd') 将中断。
  • @skyboyer “长期解决方案:避免测试状态,这是实现细节” - 如果我想根据状态变化测试渲染。那我会这样做吗?
  • @Liron,你的状态可以通过一系列事件的刺激和模拟外部来源(fetchMath.random 等)返回来实现。所以模拟和模拟。
猜你喜欢
  • 2021-06-24
  • 2018-12-16
  • 2021-01-08
  • 2020-08-27
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
  • 2017-02-12
  • 2019-02-20
相关资源
最近更新 更多