[英]How to test an unmounted React component's method that relies on setState?
I have implemented a component (for a typing training app) which tracks key presses on global scope like this: 我已经实现了一个组件(用于打字培训应用程序),该组件可以在全局范围内跟踪按键,如下所示:
class TrainerApp extends React.Component {
constructor() {
// ...
this.handlePress = this.handlePress.bind(this);
}
handlePress(event) {
const pressedKey = event.key;
const task = this.state.task;
const expectedKey = task.line[task.position];
const pressedCorrectly = pressedKey == expectedKey;
this.setState(prevState => {
const newPosition = prevState.task.position +
(pressedCorrectly ? 1 : 0);
return {
// ...prevState, not needed: https://reactjs.org/docs/state-and-lifecycle.html#state-updates-are-merged
task: {
...prevState.task,
position: newPosition,
mistakeAtCurrentPosition: !pressedCorrectly
}
}
})
}
componentDidMount() {
document.addEventListener(this.keyEventTypeToHandle,this.handlePress);
}
componentWillUnmount () {
document.removeEventListener(this.keyEventTypeToHandle,this.handlePress);
}
...
}
and I'd like to write some unit-tests using Jest. 我想用Jest编写一些单元测试。 My initial idea was: 我最初的想法是:
describe('TrainerApp.handlePress should',() => {
test('move to the next char on correct press',() => {
const app = new TrainerApp();
app.state.task.line = 'abc';
app.state.task.position = 0;
const fakeEvent = { key: 'a' };
app.handlePress(fakeEvent);
expect(app.state.task.position).toBe(1);
});
...
});
but the problem is app.handlePress
relies on usage of this.setState
which is not defined when the component is not mounted yet. 但是问题是app.handlePress
依赖于app.handlePress
用法,当尚未安装组件时, this.setState
无法定义this.setState
。 Of'course I can modify the app
like this: 当然,我可以这样修改app
:
test('move to the next char on correct press',() => {
const app = new TrainerApp();
app.setState = jest.fn(function(handler) {
this.state = handler(this.state);
});
app.state.task.line = 'abc';
app.state.task.position = 0;
const fakeEvent = { key: 'a' };
app.handlePress(fakeEvent);
expect(app.state.task.position).toBe(1);
});
or even like this: 甚至像这样:
class ExplorableTrainerApp extends TrainerApp {
setState(handler) {
this.state = handler(this.state);
}
}
test('move to the next char on correct press',() => {
const app = new ExplorableTrainerApp();
app.state.task.line = 'abc';
app.state.task.position = 0;
const fakeEvent = { key: 'a' };
app.handlePress(fakeEvent);
expect(app.state.task.position).toBe(1);
});
but this seems a very fragile approach (here I rely on the fact that .setState
is called with the function argument while it can be called with just newState
argument and hence I'm testing implementation details, instead of just the behaviour. Is there a more robust way to test this? 但这似乎是一种非常脆弱的方法(在此我依靠的事实是, .setState
是使用函数参数调用的,而它只能使用newState
参数调用,因此,我正在测试实现细节,而不仅仅是行为。更强大的方法来测试这一点?
有一些用于测试React组件的框架, Enzyme和react-testing-library都很流行并且得到了很好的支持。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.