javascript - 如何测试依赖于 setState 的未挂载 React 组件的方法?

标签 javascript reactjs testing jestjs

我已经实现了一个组件(用于打字训练应用程序),它像这样在全局范围内跟踪按键:

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);
    }
    ...
}

而且我想使用 Jest 编写一些单元测试。我最初的想法是:

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);
    });
    ...
});

但问题是 app.handlePress 依赖于 this.setState 的使用,当组件尚未安装时它未定义。当然,我可以像这样修改 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);
});

甚至像这样:

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);
});

但这似乎是一种非常脆弱的方法(这里我依赖于这样一个事实,即 .setState 是用函数参数调用的,而它可以只用 newState 参数调用,并且因此,我正在测试实现细节,而不仅仅是行为。是否有更可靠的方法来测试它?

最佳答案

有一些用于测试 React 组件的框架,Enzymereact-testing-library既受欢迎又得到很好的支持。

关于javascript - 如何测试依赖于 setState 的未挂载 React 组件的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54612375/

相关文章:

javascript - 使滚动侧边栏停在页脚处

reactjs - Firebase 配置中的 React 环境变量错误 'Unexpected token'

reactjs - 如何在生产中为 Docs 插件的 React Storybook 启用 Prop 类型

testing - 在线自动化测试类(class)

javascript - 自定义元素模板标签不渲染canvas标签元素

javascript - 使用大数据获取数组对象中的值

javascript - 有什么方法可以使用 Javascript 从 Dropbox 注销用户吗?

reactjs - 如何避免在功能组件事件处理程序中绑定(bind)/lambda?

android - 如何在android单元测试期间检查 Activity 是否显示对话框

java - 一个junit测试用例运行后,是否应该删除与这个测试用例相关的测试数据?