我的组件中有以下功能:
method(args) {
fetch(args)
.then((response) => {
this.setState({
element: response
error: false
});
})
.catch((error) => {
this.setState({
error: true
});
});
}
我正在尝试为它编写单元测试,所以我使用fetch-mock和自定义响应模拟了fetch调用。我想检查调用此方法时是否更新状态,并且它似乎不起作用。我正在使用酶,期望和sinon,并且在设置component.setState = sinon.spy或将其删除时,未能成功调用间谍。我如何检查是否使用某些元素调用了setState,或者我的单元测试方法是错误的?
答案 0 :(得分:3)
在实例化组件之前,您似乎需要在原型中监视/存根setState
。我有一个类似的问题,只是间谍实例的setState
方法不起作用。基于https://medium.com/@tjhubert/react-js-testing-setstates-callback-907df1fe720d,这是sinon的一种方法:
<强> Component.js 强>
...
method {
this.setState({property:'value'})
}
...
<强> Component.test.js 强>
...
const setState = sinon.stub(Component.prototype, ‘setState’);
const component = shallow(<Component />);
component.instance().method();
expect(setState).to.be.calledOnce;
...
注意:我的用例是使用jasmine,并且避免渲染以测试行为,所以我知道的解决方案看起来像:
Component.prototype.setState = jasmine.createSpy();
const sut = new Component();
sut.method();
expect(sut.setState).toHaveBeenCalledWith({property:'value'});
答案 1 :(得分:0)
假设在组件安装并且方法已被存根时调用该方法,请尝试:
it('should update state with response', () => {
const wrapper = mount(<Component />);
return Promise.resolve().then(() => {
expect(wrapper.state('error')).to.be.false;
});
});
返回一个promise允许你以比在setTimeout中使用回调更少hacky的方式测试异步行为。
我使用sinon作为存根,所以在测试中我会有这样的东西:
sinon.stub(window, 'fetch').resolves(mockedResponse);
答案 2 :(得分:0)
您可以暂时模拟/替换组件的setState()
方法并等待其下一次执行。这样的事情可能会起到作用:
function onNextSetState(component) {
const instance = component.instance()
const originalSetState = instance.setState.bind(instance)
return new Promise(resolve => {
instance.setState = (state, callback) => {
originalSetState(state, (...args) => {
instance.setState = originalSetState
resolve()
if (callback) {
callback(...args)
}
}
}
}
}
it('should update state with response', async () => {
const component = mount(<Component />)
component.instance().method() // we assume this runs .setState inside()
await onNextSetState(component) // we wait for the next re-render
// we can be sure the state is what we want it to be:
expect(component.state('error')).toBe(false)
})
请注意,如果您想多次等待,可能更容易/更好地使用Observable而不是Promise。
答案 3 :(得分:0)
我能够使用以下内容存根setState:
let setStateStub = sinon.stub(prototype, 'setState')
完成存根后,您还需要恢复()原始文件。 您可以通过在存根之后添加以下内容来执行此操作:
setStateStub.restore()
:)