Material UI + Enzyme 测试组件
Posted
技术标签:
【中文标题】Material UI + Enzyme 测试组件【英文标题】:Material UI + Enzyme testing component 【发布时间】:2018-11-27 16:58:35 【问题描述】:我在 React 中有一个组件,我正在尝试用 Jest 进行测试,不幸的是测试没有通过。
组件代码:
import React, Component from 'react';
import ProductItem from '../ProductItem/ProductItem';
import AppBar from "@material-ui/core/es/AppBar/AppBar";
import Tabs from "@material-ui/core/es/Tabs/Tabs";
import Tab from "@material-ui/core/es/Tab/Tab";
import connect from 'react-redux';
class ProductsTabsWidget extends Component
state =
value: 0
renderTabs = () =>
return this.props.tabs.map((item, index) =>
return item.products.length > 0 ? (<Tab key=index label=item.title/>) : false;
)
handleChange = (event, value) =>
this.setState(value);
;
renderConentActiveTab = () =>
if (this.props.tabs[this.state.value])
return this.props.tabs[this.state.value].products.map((productIndex) =>
return (<ProductItem key=productIndex ...this.props.products[productIndex] />);
);
render()
let tabs = null;
let content = null;
if (this.props.tabs)
tabs = this.renderTabs();
content = this.renderConentActiveTab();
return (
<div>
<AppBar position="static" color="default">
<Tabs
value=this.state.value
onChange=this.handleChange
indicatorColor="primary"
textColor="primary"
centered
scrollButtons="auto"
>
tabs
</Tabs>
</AppBar>
<div className="productWidget">
<div className="wrapper">
content
</div>
</div>
</div>
)
const mapStateToProps = state =>
return
products: state.product.products,
export default connect(mapStateToProps)(ProductsTabsWidget);
我已经尝试为这个组件编写适当的测试,代码如下:
import React from 'react';
import configure, shallow from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import ProductsTabsWidget from "./ProductsTabsWidget";
configure(adapter: new Adapter());
describe('ProductsTabsWidget - component', () =>
let wrapper;
beforeEach(() =>
wrapper = shallow(<ProductsTabsWidget/>);
);
it('renders with minimum props without exploding', () =>
wrapper.setProps(
tabs: [],
products:[]
);
expect(wrapper).toHaveLength(1);
);
)
但是当我运行测试时出现错误:
Test suite failed to run
F:\PRACA\reactiveShop\node_modules\@material-ui\core\es\AppBar\AppBar.js:1
("Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest)import _extends from "@babel/runtime/helpers/builtin/extends";
^^^^^^
SyntaxError: Unexpected token import
at new Script (vm.js:51:7)
at Object.<anonymous> (src/components/product/ProductsTabsWidget/ProductsTabsWidget.js:3:15)
我曾尝试使用shallow
、mount
、render
进行测试,但没有帮助。我错过了什么?
我的应用程序是在 create-react-app
上创建的。
【问题讨论】:
SyntaxError: Unexpected token import
似乎是 Babel 配置错误,它不应该出现在基本的 CRA 设置中,也许你 eject
ed 它的一些功能?一般来说,这个问题似乎与配置jest: Test suite failed to run, SyntaxError: Unexpected token import有关。
【参考方案1】:
当您使用 @material-ui
时会有所不同。
您必须使用 @material-ui
的内置 API。如createMount
,createShallow
,createRender
为了使用酶的shallow
,mount
&render
。
这些 API 构建在 enzyme
之上,因此您不能直接使用 enzyme
来测试 @material-ui
。
Shallow
使用 @material-ui 渲染的示例
import createShallow from '@material-ui/core/test-utils';
describe('<MyComponent />', () =>
let shallow;
before(() =>
shallow = createShallow();
);
it('should work', () =>
const wrapper = shallow(<MyComponent />);
);
);
参考:Official Docs of @material-ui
【讨论】:
我知道这有点“旧”的帖子,但我不认为这是完全正确的。我在一个项目(称为 mystyle)中非常使用通过我自己的 npm 包公开的材料 UI,我在其中设置了我的组件的样式。然后将该包导入另一个项目(myapp),我在其中执行测试(即,我使用自己的组件和引擎盖下的材质 UI)。 myapp 中的测试是使用酶和玩笑编写的。他们工作得很好。 Material-UI 正在弃用他们的测试工具,并且将不再出现在 v5 中。【参考方案2】:以下是从create-react-app
和@material-ui
的角度提供更完整答案的谦虚尝试。
1.
直接在src
文件夹中创建setupTests.js
并粘贴以下代码。
import configure from "enzyme";
import Adapter from "enzyme-adapter-react-16";
configure( adapter: new Adapter() );
2.
以下是使用material-ui
组件的react无状态组件。
import React from "react";
import TextField from "@material-ui/core/TextField";
const SearchField = props => (
<TextField InputProps= disableUnderline: true fullWidth
placeholder=props.placeholder
onChange=props.onChange
/>
);
export default SearchField;
请注意,在上面的组件中,组件期望父组件传递 placeholder
和 onChange()
事件处理程序的 props
3.
进入上述组件的测试用例,我们可以用material-ui
建议的方式或pure enzyme
样式编写。两者都可以。
Pure Enzyme
风格
import React from "react";
import mount from "enzyme";
import TextField from "@material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField Enzyme mount() ", () =>
const fieldProps =
placeholder: "A placeholder",
onChange: jest.fn()
;
const Composition = props =>
return <SearchField ...fieldProps />;
;
it("renders a <TextField/> component with expected props", () =>
const wrapper = mount(<Composition />);
expect(wrapper.childAt(0).props().placeholder).toEqual("A placeholder");
expect(wrapper.childAt(0).props().onChange).toBeDefined();
);
it("should trigger onChange on <SearchField/> on key press", () =>
const wrapper = mount(<Composition />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
);
it("should render <TextField />", () =>
const wrapper = mount(<Composition />);
expect(wrapper.find(TextField)).toHaveLength(1);
expect(wrapper.find(TextField).props().InputProps.disableUnderline).toBe(
true
);
);
);
Material UI
风格
import React from "react";
import createMount from "@material-ui/core/test-utils";
import TextField from "@material-ui/core/TextField";
import SearchField from "../SearchField";
describe("SearchField", () =>
let mount;
const fieldProps =
placeholder: "A placeholder",
onChange: jest.fn()
;
beforeEach(() =>
mount = createMount();
);
afterEach(() =>
mount.cleanUp();
);
it("renders a <TextField/> component with expected props", () =>
const wrapper = mount(<SearchField ...fieldProps />);
expect(wrapper.props().placeholder).toEqual("A placeholder");
expect(wrapper.props().onChange).toBeDefined();
);
it("should trigger onChange on <SearchField/> on key press", () =>
const wrapper = mount(<SearchField ...fieldProps />);
wrapper.find("input").simulate("change");
expect(fieldProps.onChange).toHaveBeenCalled();
);
);
5.
你得到的错误是由于babel
没有机会处理你的文件。 create-react-app
期望您像 yarn run test
那样运行测试,而不是像 jest your/test/file.js
那样运行测试。如果你使用后者babel
将不会是employed
。
如果您想使用jest
运行该文件,您必须编写一个jest.config.js
文件或在package.json
文件中配置jest
以使用babel-jest
+ other babel dependencies
在开玩笑之前转译您的代码尝试执行测试。
昨天我第一次尝试使用@material-ui
时,我在同一条船上,来到这里以获得更完整的答案。
【讨论】:
那么在您的情况下,您使用什么命令来运行测试?npm test
或 yarn test
?【参考方案3】:
这样的事情对我有用:
import createMount from '@material-ui/core/test-utils';
const WrappedComponent = () =>
<MUIThemeStuffEtc>
<MyComponent />
</MUIThemeStuffEtc>
const render = createMount();
const wrapper = render(<WrappedComponent />);
const state = wrapper.find(MyComponent).instance().wrappedInstance.state
【讨论】:
以上是关于Material UI + Enzyme 测试组件的主要内容,如果未能解决你的问题,请参考以下文章
酶不模拟 React Material-UI v1 上的更改事件 - 选择组件
对 Material UI Select 组件的更改做出反应测试库
如何使用 react-testing-library 测试包装在 withStyles 中的样式化 Material-UI 组件?