通过ajax调用在componentDidMount中正确设置测试状态

Testing state gets set correctly within componentDidMount from an ajax call

本文关键字:设置 测试 状态 ajax 调用 componentDidMount 通过      更新时间:2023-09-26

在我的react组件

中有以下代码
componentDidMount() {
    ajax.call().then((data)=> {
        this.setState({a:data.a});
    });
}

我正在调用一个返回promise的函数。

我的测试是这样的,当我试图测试状态是否从已解决的承诺中得到正确设置时:

        it('should set state of a', (done)=> {
            let ajax = {
                call: ()=>{}
            };
            spyOn(ajax, 'call').and.returnValue(Promise.resolve({a:'a'}));
            let component = TestUtils.renderIntoDocument(<MyComp/>);
            expect(component.state.a).toEqual('a');
        });

我很确定状态实际上是从承诺返回的数据中得到设置,但问题是我没有地方可以调用茉莉花'done()'函数来告诉茉莉花异步操作已经完成,并且可以测试对状态的断言。

React社区大多同意通过"好像"它是同步出现的,所以可以快照。这使我们的视图作为一个单一状态变量的函数,并使我们的代码易于测试。如果你没有在架构上投入——我建议你尝试像FLUX这样的架构,看看常见的库,比如redux和este。

也就是说,像您那样在AJAX之后显式地设置组件的状态是完全可以的。我将把测试分成两部分:

  • 设置一个state变量来返回AJAX,您可以通过简单地检查对象是否更改来测试这一点。
  • 调用render来重新渲染你正在测试的组件(而不是setState)。

然后,您可以测试呈现和承诺设置不同的状态,使您的呈现测试易于推理(它们是同步的)和AJAX测试容易(它只是对象)。

一般来说,当你用mocha测试承诺时,你可以使用专用的承诺语法,因为你使用的是React,你也在使用Babel,所以你不妨在你的代码中使用新的JavaScript特性:

it('does ajax', async function(){ // can also `async () =>`
    var result = await ajax.call(); // call the ajax, get response, can be mocked
    var state = result;
    var str = React.renderToString(<MyComp prop={result} />);
    // assert against the returned HTML, can also test against DOM
});