Javascript 如何测试shouldComponentUpdate方法?
我想测试一下这个方法,Javascript 如何测试shouldComponentUpdate方法?,javascript,reactjs,testing,enzyme,sinon,Javascript,Reactjs,Testing,Enzyme,Sinon,我想测试一下这个方法,shouldComponentUpdate,但是我编写的测试没有捕捉到副作用。我如何测试这个 我已经尝试了此处提出的解决方案,但其中存在一些问题,我将在代码中说明: 我尝试过使用shallow而不是mount,但当我这样做时,我的测试失败了: expect(shouldComponentUpdate).to.have.property("callCount", 1); // AssertionError: expected [Function: proxy]
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);
});
失败于
AssertionError: expected false to equal true
为什么会发生这种情况?我想
应该组件更新
应该返回真
?稍后,我希望测试状态和本地存储的副作用,但我不理解这个错误。您处理的shouldComponentUpdate生命周期是错误的。您不需要在其中设置state,而是只返回一个布尔值(true或false),让React知道何时重新呈现DOM。这允许您阻止来自外部道具的更新。例如:
shouldComponentUpdate(nextProps, nextState) {
return this.state.newStorage !== nextState.newStorage
}
static getDerivedStateFromProps(props, state) {
return props.storage.key !== state.storageKey
? { storageKey: props.storage.key }
: null
}
上述状态:如果当前新闻存储状态与下一个新闻存储状态不匹配,则重新呈现组件上述操作将阻止重新招标组件时的道具更改。如果更改了存储
道具,它将不会更新此组件,因为状态未更改。您希望使用shouldComponentUpdate来防止不必要的双重重新渲染和/或防止父组件的重新渲染不必要地重新渲染子组件。在这种情况下,您不需要使用此生命周期方法
相反,您应该在渲染前使用for props更新状态,或者在渲染后使用for props更新状态
在您的情况下,因为您只想在this.props.storageValue
发生更改时更新状态,所以您应该使用组件diddupdate
:
componentDidUpdate(prevProps) {
if (this.props.storageValue !== prevProps.storageValue) {
localStorage.setItem(constantFile.storageKey, nextProps.storageValue);
localStorage.setItem(constantFile.timestampKey, now());
this.setState({ newStorage: nextProps.storageValue });
}
}
上面检查当前道具是否与以前的道具不匹配,然后更新状态以反映更改
您将无法使用静态getDerivedStateFromProps
,因为旧道具和新道具之间没有比较,只有与传入道具和当前状态的比较。也就是说,如果您以与存储道具直接相关的状态存储某些内容,则可以使用它。例如,如果您将道具中的密钥存储到状态中。如果道具密钥要更改,并且它与状态中的当前密钥不匹配,那么它将更新状态以反映密钥更改。在这种情况下,您将返回对象
以更新状态,或返回null
以不更新状态
例如:
shouldComponentUpdate(nextProps, nextState) {
return this.state.newStorage !== nextState.newStorage
}
static getDerivedStateFromProps(props, state) {
return props.storage.key !== state.storageKey
? { storageKey: props.storage.key }
: null
}
当涉及到测试时,您需要手动更新道具以影响状态更改。通过针对状态更改进行测试,您将间接针对
componentdiddupdate
进行测试
例如(您必须这样做,否则状态将不会更新——我还建议导出并导入类,而不是使用Redux连接的组件):
从“./MyComponent.js”导入{MyComponent};
const initialProps={storageValue::};
描述(“测试组件”,()=>{
让包装纸;
在每个之前(()=>{
包装器=mount();
})
它(“当‘storageValue’道具发生更改时更新‘newStorage’状态,()=>{
setProps({storageValue:“test”});
expect(wrapper.state('NewStorage')).toEqual(…);//这应该会更新NewStorage状态
setProps({someOtherProp:“hello”)};
expect(wrapper.state('NewStorage')).toEqual(…);//这不应更新NewStorage状态
});
});
您处理的shouldComponentUpdate生命周期是错误的。您没有在其中设置状态,而是只返回一个布尔值(true或false),让React知道何时重新呈现DOM。这允许您阻止来自外部道具的更新。例如:
shouldComponentUpdate(nextProps, nextState) {
return this.state.newStorage !== nextState.newStorage
}
static getDerivedStateFromProps(props, state) {
return props.storage.key !== state.storageKey
? { storageKey: props.storage.key }
: null
}
上述状态:如果当前新闻存储状态与下一个新闻存储状态不匹配,则重新呈现组件。上述状态将阻止属性更改,从而无法重新呈现组件。如果更改了存储
属性,则不会更新此组件,因为状态未更改。是否要使用shouldcomponentupdatee以防止不必要的双重重新渲染和/或防止父组件的重新渲染不必要地重新渲染子组件。在这种情况下,您不需要使用此生命周期方法
相反,您应该在渲染前使用for props更新状态,或者在渲染后使用for props更新状态
在您的情况下,因为您只想在this.props.storageValue
发生更改时更新状态,所以您应该使用组件diddupdate
:
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
,因为旧的和新的道具之间没有比较,而只比较传入的道具和当前状态。也就是说,如果您以与存储道具直接相关的状态存储某个东西,则可以使用它。例如,如果您从道具和进入状态。如果道具密钥要更改并且与当前状态中的密钥不匹配,则它将更新状态以反映密钥更改。在这种情况下,您将返回对象以更新状态,或返回null以不更新状态
例如:
shouldComponentUpdate(nextProps, nextState) {
return this.state.newStorage !== nextState.newStorage
}
static getDerivedStateFromProps(props, state) {
return props.storage.key !== state.storageKey
? { storageKey: props.storage.key }
: null
}
说到测试,您需要手动更新道具以影响状态更改。通过针对状态更改进行测试,您将间接针对componentdiddupdate
进行测试
例如(您必须这样做,否则状态将不会更新——我还建议导出并导入类,而不是使用Redux连接的组件):
从“./My”导入{MyComponent}