我在为调用 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 并编写一个包含对 setImmediatewrapper.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);
        });
    });

});

正如我所说,如果我的 expect 语句失败,这会让Jest感到震惊 . 这让我觉得我做错了什么 . 是否有一些更简单的方法来进行像这样的测试工作?

我已经尝试使用 setTimeout 而不是 setImmediate 这样可行,但是我并没有真正获得任何东西并且花费了几行代码,因为我需要使用async done test参数 . 它没有炸毁Jest,但是如果没有 try..catch..finally 它会表现得很糟糕 . 我也尝试了 asyncawait ,但我无法使用该代码 .

当使用 setImmediate 我可以这样做以防止崩溃,但它使我的代码非常罗嗦:

try {
   expect(wrapper.contains(statusParagraph)).toBe(true);
} catch (e) {
   console.log(e);
}

有关如何使这更简单和更健壮的任何想法?