ReactWrapper::state() 只能在类组件单元测试 Jest 和 Enzyme 上调用
Posted
技术标签:
【中文标题】ReactWrapper::state() 只能在类组件单元测试 Jest 和 Enzyme 上调用【英文标题】:ReactWrapper::state() can only be called on class components Unit Testing Jest and 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'
的默认导出是什么样的?
【参考方案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,你的状态可以通过一系列事件的刺激和模拟外部来源(fetch
,Math.random
等)返回来实现。所以模拟和模拟。以上是关于ReactWrapper::state() 只能在类组件单元测试 Jest 和 Enzyme 上调用的主要内容,如果未能解决你的问题,请参考以下文章