【发布时间】:2018-12-13 00:51:40
【问题描述】:
我一直在尝试了解如何测试在componentDidMount 期间运行异步获取的已安装组件。
问题是我可以让它等待初始提取触发,而不是等待从承诺中解决所有链。
这是一个例子:
import React from "react";
class App extends React.Component {
state = {
groceries: [],
errorStatus: ""
};
componentDidMount() {
console.log("calling fetch");
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 App;
测试:
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
import { mount } from 'enzyme'
import App from './App';
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('componentDidMount', () => {
it('sets the state componentDidMount', async () => {
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 = await mount(<App />)
await renderedComponent.update()
console.log('finished test for 200')
expect(renderedComponent.state('groceries').length).toEqual(2)
})
it('sets the state componentDidMount on error', async () => {
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 = await mount(<App />)
await renderedComponent.update()
console.log('finished test for 500')
expect(renderedComponent.state('errorStatus')).toEqual('Error fetching groceries')
})
})
})
当它运行时,我会收到以下控制台日志记录顺序(注意测试完成,然后记录状态已设置):
console.log src/App.test.js:22
starting test for 200
console.log src/App.js:10
calling fetch
console.log src/App.js:36
parse json
console.log src/App.test.js:39
finished test for 200
console.log src/App.js:42
setting state
我已经为我的代码创建了一个示例沙箱:
这在我的应用程序中被抽象了很多,因此更改代码本身要困难得多(例如,我想在具有 redux 存储的更高组件上进行测试,而这个更低的组件调用 fetch,并设置最终通过 thunk 存储)。
这是如何测试的?
【问题讨论】:
标签: javascript reactjs fetch jestjs enzyme