安装时如何从酶实例中获取HOC包装的组件功能?

时间:2018-12-13 21:34:25

标签: javascript reactjs jestjs enzyme

我有父级->子级组件,并且子级在 mounted: function(){ this.activeLink = this.$route.path; }, 内部运行访存。提取操作在Redux存储区中位于父级上方的状态,这会导致子级组件的显示方式不同。

孩子也使用componentDidMount material-ui,因此它在组件周围创建了HOC。

在测试中,我需要安装父组件,找到子组件,然后查看访存状态是否已正确更改并导致子项更新。

到目前为止,我的解决方案是:

  • 挂上父母,找到孩子
  • 致电withStyles

但是,在child.instance().fetchFunction().then(() => expect(..))上调用instance()会返回HOC,所以我得到了错误:

  

child.instance(...)。fetchFunction不是函数

我见过的所有解决方案都使用childshallow来解决HOC问题,但是如果使用dive,我将不得不在测试中创建一个模拟存储,它将赢得实际上并没有将其作为集成测试进行测试。

我可以测试单个提取调用,然后使用shallow测试组件,然后将props传递给组件,就好像状态已更改一样,但这不能证明它们都可以一起工作。

以下是我在其中复制了该问题的密码和邮箱:

Edit Testing Async componentDidMount

以下是一些示例代码(基本上是codesandbox):

shallow

App.js

import React from "react"; import Child from "./Child"; class App extends React.Component { render() { return <Child />; } } export default App;

Child.js

import React from "react"; import { withStyles } from "@material-ui/core/styles"; const childStyles = { margin: 0 }; class Child extends React.Component { state = { groceries: [], errorStatus: "" }; componentDidMount() { console.log("calling fetch"); this.fetchCall(); } fetchCall = () => { return fetch("/api/v1/groceries") .then(this.checkStatus) .then(this.parseJSON) .then(this.setStateFromData) .catch(this.setError); }; checkStatus = results => { if (results.status >= 400) { console.log("bad status"); throw new Error("Bad Status"); } return results; }; setError = () => { console.log("error thrown"); return this.setState({ errorStatus: "Error fetching groceries" }); }; parseJSON = results => { console.log("parse json"); return results.json(); }; setStateFromData = data => { console.log("setting state"); return this.setState({ groceries: data.groceries }); }; render() { const { groceries } = this.state; return ( <div id="app"> {groceries.map(grocery => { return <div key={grocery.id}>{grocery.item}</div>; })} </div> ); } } export default withStyles(childStyles)(Child);

App.test.js

1 个答案:

答案 0 :(得分:3)

在写完这篇文章后,我找到了答案,但是我觉得值得分享,因为我对此很困惑。

使用import Enzyme from "enzyme"; import Adapter from "enzyme-adapter-react-16"; import React from "react"; import { mount } from "enzyme"; import App from "./App"; import Child from "./Child"; Enzyme.configure({ adapter: new Adapter() }); const mockResponse = (status, statusText, response) => { return new window.Response(response, { status: status, statusText: statusText, headers: { "Content-type": "application/json" } }); }; describe("App", () => { describe("ChildApp componentDidMount", () => { it("sets the state componentDidMount", () => { console.log("starting test for 200"); global.fetch = jest.fn().mockImplementation(() => Promise.resolve( mockResponse( 200, null, JSON.stringify({ groceries: [{ item: "nuts", id: 10 }, { item: "greens", id: 3 }] }) ) ) ); const renderedComponent = mount(<App />); const childApp = renderedComponent.find(Child); childApp .instance() .fetchCall() .then(() => { console.log("finished test for 200"); expect(childApp.state("groceries").length).toEqual(2); }); }); it("sets the state componentDidMount on error", () => { console.log("starting test for 500"); window.fetch = jest .fn() .mockImplementation(() => Promise.resolve( mockResponse( 400, "Test Error", JSON.stringify({ status: 400, statusText: "Test Error!" }) ) ) ); const renderedComponent = mount(<App />); const childApp = renderedComponent.find(Child); childApp .instance() .fetchCall() .then(() => { console.log("finished test for 500"); expect(childApp.state("errorStatus")).toEqual( "Error fetching groceries" ); }); }); }); }); (组件显示名称)代替使用app.find(Child)(组件构造函数)。这将找到实际的组件,而不是临时包装的组件。

enzyme docs for find(selector)