如何测试 componentDidMount 时调用的组件函数?
How to test a component function being called when componentDidMount?
我有一个 React JS 组件 MyComponent
,我想测试以下用例:
It should call updateSomething()
when component on mount
我想出了以下代码:
被测系统 (SUT)
export class MyComponent extends React.Component<Props, State> {
public componentDidMount() {
console.log("componentDidMount"); // Debug purpose.
this.fetchSomething()
.then(() => {
console.log("fetchSomething"); // Debug purpose.
this.updateSomething();
});
}
// These are public for simplicity
public async fetchSomething(): Promise<any> { }
public updateSomething() {
console.log("updateSomething"); // Debug purpose.
}
}
测试
it("should update something, when on mount", () => {
const props = { ...baseProps };
sinon.stub(MyComponent.prototype, "fetchSomething").resolves();
const spy = sinon.spy(MyComponent.prototype, "updateSomething");
shallow(<MyComponent {...props} />);
sinon.assert.calledOnce(spy);
});
结果是测试失败 AssertError: expected updateSomething to be called once but was called 0 times
但所有三个 console.log()
都打印出来了。
我的理解是因为我想在挂载时测试事件,我必须在它创建之前 spy/stub 它,因此我必须监视 MyComponent.Prototype
。此外,对于 fetchSomething()
,我必须对异步调用进行存根处理并使其成为 .resolves()
以使其继续进行。
但我不明白它怎么还能console.log("updateSomething")
而不被窥探。
我不知道 sinon
,我也不知道 ts
,但是对于简单的 js
和 jest
,它会像这样:
fetchSomething() = Promise.resolve();
然后,在您的测试中,您不必模拟它而只需使用:
const spy = jest.spyOn(MyComponent.prototype, 'updateSomething');
查看是否被调用:
expect(spy).toHaveBeenCalled();
根据 中的 comments/answer,断言在 .updateSomething
被调用之前出现。要解决这个问题,我会等待 componentDidMount
生命周期方法。
所以固定程序如下:
// SUT
public async componentDidMount() {
//...
return this.fetchSomething()
.then(() => {
//...
});
}
// Test
it("should update something, when on mount", () => {
const props = { ...baseProps };
// Disable lifecycle here to enable stub in between.
const wrapper = shallow(<MyComponent {...props} />, { disableLifecycleMethods: true });
sinon.stub(wrapper.instance(), "fetchSomething").resolves();
const stub = sinon.stub(wrapper.instance(), "updateSomething");
// Actually call component did mount.
wrapper.instance().componentDidMount().then(() => {
sinon.assert.calledOnce(stub);
});
});
我有一个 React JS 组件 MyComponent
,我想测试以下用例:
It should call
updateSomething()
when component on mount
我想出了以下代码:
被测系统 (SUT)
export class MyComponent extends React.Component<Props, State> {
public componentDidMount() {
console.log("componentDidMount"); // Debug purpose.
this.fetchSomething()
.then(() => {
console.log("fetchSomething"); // Debug purpose.
this.updateSomething();
});
}
// These are public for simplicity
public async fetchSomething(): Promise<any> { }
public updateSomething() {
console.log("updateSomething"); // Debug purpose.
}
}
测试
it("should update something, when on mount", () => {
const props = { ...baseProps };
sinon.stub(MyComponent.prototype, "fetchSomething").resolves();
const spy = sinon.spy(MyComponent.prototype, "updateSomething");
shallow(<MyComponent {...props} />);
sinon.assert.calledOnce(spy);
});
结果是测试失败 AssertError: expected updateSomething to be called once but was called 0 times
但所有三个 console.log()
都打印出来了。
我的理解是因为我想在挂载时测试事件,我必须在它创建之前 spy/stub 它,因此我必须监视 MyComponent.Prototype
。此外,对于 fetchSomething()
,我必须对异步调用进行存根处理并使其成为 .resolves()
以使其继续进行。
但我不明白它怎么还能console.log("updateSomething")
而不被窥探。
我不知道 sinon
,我也不知道 ts
,但是对于简单的 js
和 jest
,它会像这样:
fetchSomething() = Promise.resolve();
然后,在您的测试中,您不必模拟它而只需使用:
const spy = jest.spyOn(MyComponent.prototype, 'updateSomething');
查看是否被调用:
expect(spy).toHaveBeenCalled();
根据 .updateSomething
被调用之前出现。要解决这个问题,我会等待 componentDidMount
生命周期方法。
所以固定程序如下:
// SUT
public async componentDidMount() {
//...
return this.fetchSomething()
.then(() => {
//...
});
}
// Test
it("should update something, when on mount", () => {
const props = { ...baseProps };
// Disable lifecycle here to enable stub in between.
const wrapper = shallow(<MyComponent {...props} />, { disableLifecycleMethods: true });
sinon.stub(wrapper.instance(), "fetchSomething").resolves();
const stub = sinon.stub(wrapper.instance(), "updateSomething");
// Actually call component did mount.
wrapper.instance().componentDidMount().then(() => {
sinon.assert.calledOnce(stub);
});
});