我有一个组件可以在fetch
中执行两个componentDidMount
操作。我想测试一下,我必须说实话:我不清楚如何继续进行。
关键是似乎没有“标准”的方式来进行。基本上我发现更令人困惑的是:
当我应该使用一种方法/库而不是另一种时,我不是很清楚。
这是我的功能的简化版本:
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});
});
}
我想测试的是:
GET
)运行良好,请测试更新的state
尊重我想要的表单(因此data
形成良好/不良的情况都是如此)。state
error
是否已更新
当然我需要一个模拟机制来模拟两个答案(对于GET
和POST
操作)但不清楚我该怎么做,或者如何测试结果。
答案 0 :(得分:2)
您无需模拟api调用。 fetch
有自己的库测试,因此您无需测试fetch
是否有效。但是,如果您确实需要测试方法,可以使用jest
- https://facebook.github.io/jest/docs/en/asynchronous.html。忘掉jest-fetch-mock。你可以测试:
componentDidMount
是否被调用?yourMethod
被叫了吗?yourMethod
完成后,是否发生了更改? (你的新州是预期的州吗?)请记住,不要自己测试库,也不要深入到组件树中。你应该只进行原子测试。一次一件事。
现在:
您可以使用async/await
或只测试获取本身。首先,您应该将fetch
'es抽象为他们自己的方法。现在。如果您所做的只是连接承诺,并且如果您正确地获取所有内容,则设置状态,您只需要在测试文件上解析该承诺,并在其回调中检查状态是否已更改为您想要的状态。
同样,您需要了解所有内容:https://facebook.github.io/jest/docs/en/asynchronous.html#promises
答案 1 :(得分:0)
这里的技巧是在接收到来自远程源的数据后声明状态/快照。即使进行了模拟,它仍然是异步进行的。所以你可以使用例如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 );
});
});
答案 2 :(得分:0)
我们通常test the state
通过模拟提取调用已更改了生命周期方法。 Avoid using setTimeout
在测试中,因为您永远不知道fetchMock将花费多少时间,因此您可以使用await
代替它。例如:
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);
})
})