[英]How to test react components when fetch in componentDidMount?
I have component where I perform two fetch
operations in componentDidMount
.我有一个组件,我在componentDidMount
中执行两个fetch
操作。 I want to test this and I have to be honest: it's not clear to me how to proceed at all.我想对此进行测试,而且我必须说实话:我根本不清楚如何进行。
The point is that it seems that there isn't a "standard" way to proceed.关键是似乎没有一个“标准”的方式来进行。 Essentially what I find more confusing is:本质上,我发现更令人困惑的是:
It's not very clear to me when I should use one approach/library instead of the other.我不太清楚什么时候应该使用一种方法/库而不是另一种。
This is a simplified version of my function:这是我的功能的简化版本:
componentDidMount() {
fetch(URL, {
method: 'GET',
}).then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("Error loading data from " + URL);
}
}).then(data => {
if (!_.isEmpty(data)) {
this.setState({
data: data,
});
} else {
throw new Error("Invalid data from " + URL);
}
}).catch(error => {
console.log(URL + ' error: ', error);
this.setState({error});
});
const payload = {...};
fetch(URL2, {
method: 'POST',
body: JSON.stringify(payload),
}).then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error("Error loading data from " + URL2);
}
}).then(data => {
if (!_.isEmpty(data2)) {
this.setState({
data2: data2
});
} else {
throw new Error("Invalid data from " + URL2);
}
}).catch(error => {
this.setState({error, isLoading: false});
});
} }
What I want to test is:我要测试的是:
GET
) went well, test the updated state
respect the form that I want (so both case where data
is well/bad formed).假设获取 ( GET
) 进行顺利,请测试更新后的state
是否符合我想要的形式(因此这两种情况下data
格式正确/错误)。state
is updated with error
假设抓取失败,测试state
更新error
Of course I will need a mocking mechanism to mock the two answers (for GET
and POST
operations) but is not clear how should I do it, or how to test the results.当然,我需要一个模拟机制来模拟这两个答案(对于GET
和POST
操作),但不清楚我应该怎么做,或者如何测试结果。
You don't need to mock the api call.您不需要模拟 api 调用。 fetch
has its own library tests so you don't need to test if fetch
works. fetch
有自己的库测试,所以你不需要测试fetch
是否有效。 But if you really need to test your method, you can just use jest
- https://facebook.github.io/jest/docs/en/asynchronous.html .但是如果你真的需要测试你的方法,你可以只使用jest
- https://facebook.github.io/jest/docs/en/asynchronous.html 。 Forget the jest-fetch-mock.忘记 jest-fetch-mock。 You can test:你可以测试:
componentDidMount
called?是否调用了componentDidMount
方法?yourMethod
called?你的方法被yourMethod
吗?yourMethod
finished, did the change occurred?在yourMethod
完成后,是否发生了变化? (Your new state is the expected one?) (你的新状态是预期的吗?)Just remember not to test the libraries themselves, or to go very deep into the component tree.请记住不要测试库本身,或者深入组件树。 You should only test atomically.您应该只进行原子测试。 One thing at a time.一心一意。
Now:现在:
You can use async/await
or just test the fetch itself.您可以使用async/await
或仅测试获取本身。 First of all, you should abstract those fetch
'es to their own methods.首先,您应该将那些fetch
抽象为它们自己的方法。 Now.现在。 If all you do is concatenate promises and if u get everything correctly u set the state, you just need to, on the test file, resolve that promise, and on its callback, check if the state changed to what you wanted.如果您所做的只是连接 promises,并且如果您正确地设置了状态,那么您只需要在测试文件上解决该 promise,并在其回调中检查状态是否更改为您想要的状态。
Again, this has all you need to know: https://facebook.github.io/jest/docs/en/asynchronous.html#promises同样,这包含您需要了解的所有信息: https ://facebook.github.io/jest/docs/en/asynchronous.html#promises
And if you need one more resource here you go: https://codereviewvideos.com/course/react-redux-and-redux-saga-with-symfony-3/video/testing-javascript-s-fetch-with-jest-happy-path如果您需要更多资源,请访问: https ://codereviewvideos.com/course/react-redux-and-redux-saga-with-symfony-3/video/testing-javascript-s-fetch-with-jest -快乐之路
The trick here is to assert state/snapshot after the data from remote source are received.这里的技巧是在接收到来自远程源的数据后断言状态/快照。 Even with mocking it's still goes asynchronously.即使有模拟,它仍然是异步的。 So you can use eg setTimeout to postpone assertion:所以你可以使用例如 setTimeout 来推迟断言:
import React from "react";
import { shallow } from "enzyme";
import sinon from "sinon";
import fetch from "node-fetch";
sinon.stub(fetch, "Promise").returns(
Promise.resolve({
json: () => Promise.resolve( { name: "Hello" } )
})
);
class Test extends React.Component {
state = {
name: "none"
};
async componentDidMount() {
const res = await fetch( "https://swapi.co/api/people/1" ),
data = await res.json();
this.setState({ name: data.name });
}
render() {
return <h1>{ this.state.name }</h1>;
}
}
describe( "component with fetch", () => {
test( "state gets updated with the fetch", ( done ) => {
const wrapper = shallow( <Test /> );
setTimeout(() => {
wrapper.update();
const state = wrapper.instance().state;
console.log(state);
done();
}, 10 );
});
});
We generally test the state
that the lifecycle methods have changed by mocking the fetch calls.我们通常通过模拟获取调用来test the state
。 Avoid using setTimeout
in tests as you never know how much time the fetchMock is gonna take, so you can use await
instead of that. Avoid using setTimeout
,因为您永远不知道 fetchMock 将花费多少时间,因此您可以使用await
代替它。 For example:例如:
import React from "react";
import {shallow} from "enzyme";
import fetchMock from "fetch-mock";
import TestComponent from "./TestComponent";
describe(() => {
it("should set the state after fetching data", () => {
// arrange
fetchMock.get(`https://www.example.com`, mockResponse);
const wrapper = shallow(<TestComponent>);
// act
await wrapper.instance().componentDidMount();
// assert
expect(wrapper.state()).toEqual(newStateObject);
})
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.