在进行单元测试时,是否可以在React中对setState方法进行存根或监视?

int*_*n17 10 unit-testing sinon reactjs enzyme

我的组件中有以下功能:

method(args) {
 fetch(args)
  .then((response) => {
    this.setState({
      element: response
      error: false
    });
  })
  .catch((error) => {
    this.setState({
      error: true
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试为它编写单元测试,所以我使用fetch-mock和自定义响应模拟了fetch调用.我想检查调用此方法时是否更新状态,并且它似乎不起作用.我正在使用酶,期望和sinon,并且在设置component.setState = sinon.spy或将其删除时,未能成功调用间谍.我如何检查是否使用某些元素调用了setState,或者我的单元测试方法是错误的?

Wil*_*ill 5

看来您需要setState在实例化组件之前在原型中进行监视/存根。我遇到了类似的问题,简单地监视setState实例的方法是行不通的。基于https://medium.com/@tjhubert/react-js-testing-setstates-callback-907df1fe720d,这是 sinon 的一种方法:

\n\n

组件.js

\n\n
...\nmethod {\n  this.setState({property:\'value\'})\n}\n...\n
Run Code Online (Sandbox Code Playgroud)\n\n

组件.test.js

\n\n
...\nconst setState = sinon.stub(Component.prototype, \xe2\x80\x98setState\xe2\x80\x99);\nconst component = shallow(<Component />);\ncomponent.instance().method();\nexpect(setState).to.be.calledOnce;\n...\n
Run Code Online (Sandbox Code Playgroud)\n\n

注意:我的用例是使用 jasmine,并避免渲染来测试行为,因此我知道有效的解决方案如下所示:

\n\n
Component.prototype.setState = jasmine.createSpy();\nconst sut = new Component();\nsut.method();\nexpect(sut.setState).toHaveBeenCalledWith({property:\'value\'});\n
Run Code Online (Sandbox Code Playgroud)\n


小智 1

假设在组件安装时调用该方法并且该方法已被存根,请尝试以下操作:

it('should update state with response', () => {
  const wrapper = mount(<Component />);

  return Promise.resolve().then(() => {
    expect(wrapper.state('error')).to.be.false;
  });
});
Run Code Online (Sandbox Code Playgroud)

返回 Promise 允许您以比在 setTimeout 中使用回调更简单的方式测试异步行为。

我使用 sinon 作为存根,所以我在测试中会有这样的东西:

sinon.stub(window, 'fetch').resolves(mockedResponse);
Run Code Online (Sandbox Code Playgroud)