我无法为调用 fetch 的React组件创建模拟Jest测试。特别是,如果我写了一个失败的测试,那么Jest会爆炸并将我踢回bash shell。要重新开始,我必须重新开始测试。
这是我的组件的精简版
class App extends Component {
constructor(props) {
super(props);
this.state = { file: 'unknown' };
}
queryServer = async() => {
const that = this;
return fetch('/api/foo')
.then(function (response) {
return response.json();
})
.then(function (json) {
that.setState(() => { return {'file': 'api.js'}; });
});
};
render() {
return (
<div>
<p>File: {this.state.file}</p>
<button id='qs' onClick={this.queryServer}>Server</button>
</div>);
}
}
然后我模拟 fetch 并编写包含对 setImmediate 和 wrapper.update 的调用的测试。这段代码有效,但如果我写了一个糟糕的测试,它就会爆炸:
describe('Jest Create React Tests', function () {
beforeEach(() => {
global.fetch = jest.fn().mockImplementation(() => {
const promise = new Promise((resolve, reject) => {
resolve({
ok: true,
json: function () {
return {file: 'api.js'};
}
});
});
return promise;
});
});
it('renders test', () => {
const wrapper = shallow(<App/>);
const fileParagraph = <p>File: api.js</p>;
wrapper.find('#qs').simulate('click');
setImmediate(() => {
wrapper.update();
expect(wrapper.contains(fileParagraph)).toEqual(true);
});
});
});
正如我所说,如果我的期望语句失败,这会让Jest感到震惊。这让我觉得我做错了什么。是否有一些更简单的方法来进行像这样的测试工作?
我尝试过使用 setTimeout 而不是 setImmediate 这样做有效,但实际上并没有给我带来任何好处,因为我需要使用几行代码异步完成测试参数。它不会爆炸Jest,但如果没有 try..catch..finally ,它会表现得很糟糕。我还尝试过异步和等待,但我无法使该代码生效。
使用 setImmediate 时,我可以这样做以防止崩溃,但这会使我的代码非常冗长:
try {
expect(wrapper.contains(statusParagraph)).toBe(true);
} catch (e) {
console.log(e);
}
如何使这更简单,更健壮?