[英]How can fetch be mocked in a class component's instance method in React?
I'm working with create-react-app, jest and enzyme. 我正在使用create-react-app,jest和酶。
I have a class component that loads "detail" data when a table row is clicked, then displays a form in a modal where the details can be edited and saved: 我有一个类组件,在单击表行时加载“详细信息”数据,然后在模式中显示一个表单,可以编辑和保存详细信息:
import React, { Component } from "react";
import fetch from "isomorphic-fetch";
import Modal from "./Modal";
export default class RecordViewer extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
currentRecord: {}
};
}
open(id) {
fetch(`api/${id}`)
.then(res => res.json())
.then(data => {
this.setState({
...this.state,
currentRecord: data.record,
showModal: true
});
});
}
render() {
<div>
<Modal visible={this.state.showModal} contents={this.state.currentRecord} />
<table>
<tr onClick={()=>this.open(1)}>
<td>Record Overview for Item 1</td>
</tr>
</table>
</div>
}
}
I want to mock the fetch function to determine if it is called or not, but also just to keep the component from trying to hit the API. 我想模拟fetch函数来确定它是否被调用,但也只是为了防止组件尝试访问API。 I want to test the contents passed to the modal, for example.
我想测试传递给模态的内容,例如。
Passing fetch in as a prop would make this easy but then this component's parent would need to know about it, which doesn't seem to make sense. 将fetch作为prop进行传递会使这很容易,但是这个组件的父级需要知道它,这似乎没有意义。
Is there a way to mock fetch with this set up? 有没有办法用这个设置模拟获取?
Perhaps there is a better way to go about testing this altogether? 也许有更好的方法来完全测试这个?
Actually you should create like a "container" component to connect business rules and "view" ex; 实际上你应该创建一个“容器”组件来连接业务规则和“查看”ex;
src/components
-> RecordViewer.js
-> RecordViewerContainer.js
So, in the RecordViewer.js
you can do like a PURE component wich just export a callback functions ex. 因此,在
RecordViewer.js
你可以像PURE组件那样只导出一个回调函数ex。
RecordViewer.js RecordViewer.js
import React, { Component } from "react";
import Modal from "./Modal";
class RecordViewer extends Component {
render() {
<div>
<Modal visible={this.props.showModal}
contents={this.props.currentRecord} />
<table>
<tr onClick={() => this.props.onOpen(1)}>
<td>Record Overview for Item 1</td>
</tr>
</table>
</div>
}
}
RecordViewer.propTypes = {
showModal: React.PropTypes.bool,
onOpen: React.PropTypes.func,
currentRecord: React.PropTypes.object
}
RecordViewer.defaultProps = {
showModal: false,
currentRecord: {},
onOpen: function(){}
}
export default RecordViewer;
RecordViewerContainer.js RecordViewerContainer.js
import React, { Component } from "react";
import fetch from "isomorphic-fetch";
import RecordViewer from "./RecordViewer";
export default class RecordViewerContainer extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
currentRecord: {}
};
}
open(id) {
fetch(`api/${id}`)
.then(res => res.json())
.then(data => {
this.setState({
...this.state,
currentRecord: data.record,
showModal: true
});
});
}
render() {
<RecordViewer currentRecord={this.state.currentRecord} showModal={this.state.showModal} />
}
}
Then you can mock the component params and separate the API calls and business rules. 然后,您可以模拟组件参数并分离API调用和业务规则。
tip: We have tools wich do this better, like redux
, altjs
, reflux
(flux implementations). 提示:我们有更好的工具,如
redux
, altjs
, reflux
(焊剂实施)。
There is a way but it's not ideal. 有一种方法,但它并不理想。 Have a look at the fetch-mock package.
看看fetch-mock包。
The reason why it's not ideal is that you will not be totally isolating your component so technically it wouldn't be a unit test any more but you didn't specify what kind of test you're writing. 它不理想的原因是你不会完全隔离你的组件,所以在技术上它不再是单元测试,但你没有指定你正在编写什么样的测试。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.