[英]How do I test the method shouldComponentUpdate?
我想测试方法shouldComponentUpdate
但是我写的测试没有发现副作用。 我该如何测试?
我已经尝试了这里提出的解决方案,但是有一些问题将在代码中显示: 如何对React Component应该进行单元测试shouldComponentUpdate方法
我尝试使用shallow
而不是mount
但是当我这样做时,我的测试此时失败了:
expect(shouldComponentUpdate).to.have.property("callCount", 1);
// AssertionError: expected [Function: proxy] to have a property 'callCount' of 1, but got 0
这是我组件的shouldComponentUpdate
函数:
shouldComponentUpdate(nextProps, nextState) {
if (this.props.storageValue !== nextProps.storageValue) {
localStorage.setItem(constantFile.storageKey, nextProps.storageValue);
localStorage.setItem(constantFile.timestampKey, now());
this.setState({
newStorage: nextProps.storageValue
});
return true;
}
...
return false;
}
这是我的测试:
it("Test shouldComponentUpdate", () => {
/* eslint-disable one-var */
const wrapper = mount(
<Provider store={store}>
<MyComponent />
</Provider>),
shouldComponentUpdate = sinon.spy(CapitalHomeAccessPointContainer.prototype, "shouldComponentUpdate");
wrapper.setProps({
storageValue: true
});
expect(shouldComponentUpdate).to.have.property("callCount", 1);
expect(shouldComponentUpdate.returned(true)).to.be.equal(true);
expect(localStorage.getItem(constantFile.timestampKey)).to.equal(someExpectedTimestamp);
});
expect(shouldComponentUpdate).to.have.property("callCount", 1);
失败于
AssertionError: expected false to equal true
为什么会这样? 我以为shouldComponentUpdate
应该返回true
? 稍后,我希望测试状态和本地存储的副作用,但我不理解此错误。
您正在处理shouldComponentUpdate生命周期错误。 您没有在其中设置setState
,而是仅返回一个boolean
(true或false)以使React知道何时重新呈现DOM。 这使您可以阻止来自外部道具的更新。 例如:
shouldComponentUpdate(nextProps, nextState) {
return this.state.newStorage !== nextState.newStorage
}
上面的状态:如果当前newStorage状态与下一个newStorage状态不匹配,则重新渲染该组件。 上面的代码将阻止prop更改重新呈现组件 。 如果您更改了storage
道具,则不会更新该组件,因为状态没有更改。 您要使用shouldComponentUpdate来防止不必要的双重重新渲染和/或防止父组件的重新渲染不必要地重新渲染子组件。 在这种情况下,您将不需要使用此生命周期方法。
相反,您应该使用静态getDerivedStateFromProps来使道具在渲染之前更新状态,或者使用componentDidUpdate在渲染之后更新状态。
在您的情况下,由于您只想在this.props.storageValue
更改时更新状态,因此您应该使用componentDidUpdate
:
componentDidUpdate(prevProps) {
if (this.props.storageValue !== prevProps.storageValue) {
localStorage.setItem(constantFile.storageKey, nextProps.storageValue);
localStorage.setItem(constantFile.timestampKey, now());
this.setState({ newStorage: nextProps.storageValue });
}
}
上面的代码检查当前道具是否与以前的道具不匹配,然后更新状态以反映更改。
您将无法使用static getDerivedStateFromProps
因为新旧道具之间没有比较,而只有传入的道具与当前状态进行了比较。 也就是说,如果您存储的状态与存储道具直接相关,则可以使用它。 例如,如果您存储了道具中的钥匙并进入状态。 如果props键要更改,并且与状态中的当前键不匹配,则它将更新状态以反映键的更改。 在这种情况下,您将返回一个object
以更新状态,或者返回null
则不更新状态。
例如:
static getDerivedStateFromProps(props, state) {
return props.storage.key !== state.storageKey
? { storageKey: props.storage.key }
: null
}
在测试时,您需要手动更新道具以影响状态更改。 通过针对状态更改进行测试,您将针对componentDidUpdate
间接测试。
例如(您必须模拟localStorage ,否则状态将不会更新-我也建议您export
class
并导入它,而不是使用Redux连接的组件):
import { MyComponent } from "../MyComponent.js";
const initialProps = { storageValue: "" };
describe("Test Component", () => {
let wrapper;
beforeEach(() => {
wrapper = mount(<MyComponent { ...initialProps } />);
})
it("updates 'newStorage' state when 'storageValue' props have changed, () => {
wrapper.setProps({ storageValue: "test" });
expect(wrapper.state('NewStorage')).toEqual(...); // this should update NewStorage state
wrapper.setProps({ someOtherProp: "hello" )};
expect(wrapper.state('NewStorage')).toEqual(...); // this should not update NewStorage state
});
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.