如何使用Jest对连接的Redux组件内的组件中的Redux操作进行单元测试

时间:2017-04-26 09:50:20

标签: unit-testing reactjs jestjs

我正在使用jestenzyme对我的React应用程序进行单元测试,而我正在努力测试连接的组件。

我有一个简单的组件,其中包含以下逻辑:

class LoginPage extends React.Component {

    componentDidMount() {
        if (!this.props.reduxReducer.appBootstrapped) {
                this.props.dispatch(ReduxActions.fadeOutAndRemoveSplashScreen(500));
        }
    }

    render() {
        return (
            <div data-page="login-page" >
                <div>This is the login page.</div>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        reduxReducer: state.reduxReducer
    }
};

export default connect(mapStateToProps, null)(LoginPage);

因此,这是一个显示包含某些文本的<div />元素的组件,但我要测试的重要部分是,在安装组件时,会调度一个操作来隐藏启动画面。 我希望这只在应用程序没有引导时发生。

我有一个简单的单元测试来测试组件是否呈现:

describe("[LoginPage Component]", () => {
    it("Renders without a problem.", () => {
        // Act.
        const wrapper = mount(
            <LoginPage store={ reduxStore } />
        );

        // Assert.
        expect(wrapper.find("div[data-page=\"login-page\"]").length).toBe(1);
    });
});

reduxStore属性是我的实际redux存储,使用以下代码创建:

const reduxStore = createStore(
    combineReducers(
        {
            reduxReducer
        }
    )
);

现在,我如何测试componentDidMount()方法,以及更多特殊方法,测试redux操作fadeOutAndRemoveSplashScreen()仅在应用程序尚未引导时调用。

我认为我需要模拟我的redux商店,但是,我是这方面的新手,现在不知道如何开始,所以一个例子将受到高度赞赏。

如果对我的实施有任何其他想法,请随时提供一些建议。

亲切的问候

1 个答案:

答案 0 :(得分:4)

我不会使用原始dispatch方法发送操作。我会用mapDispatchToProps。这使您的动作可以直接在组件道具中使用 - 这里我们使用ES6破坏作为connect方法的简写。

然后我不会嘲笑redux存储,而是在没有它的情况下测试你的组件。尝试将导出添加到class(第一行)。例如:

export class LoginPage extends React.Component {

    componentDidMount() {
        if (!this.props.reduxReducer.appBootstrapped) {
          // make sure that you are using this.props.action() not
          // just the action(), which is not connected to redux
          this.props.fadeOutAndRemoveSplashScreen(500);
        }
    }

    render() {
        return (
            <div data-page="login-page" >
                <div>This is the login page.</div>
            </div>
        );
    }
}

const mapStateToProps = (state) => {
    return {
        reduxReducer: state.reduxReducer
    }
};

export default connect(mapStateToProps, {
  fadeOutAndRemoveSplashScreen: ReduxActions.fadeOutAndRemoveSplashScreen
})(LoginPage);

然后在您的测试中,而不是导入连接的组件,导入类:

import ConnectedLoginPage, { LoginPage } from '/path/to/component';

然后只需将LoginPage传递给您想要测试的任何道具。因此,我们会将您的appBooststrapped设置为false,然后将该操作作为sinon间谍传递:

const spy = sinon.spy();
const reduxReducer = {
  appBootstrapped: false, // or true
}
const wrapper = mount(
    <LoginPage reduxReducer={reduxReducer} fadeOutAndRemoveSplashScreen={spy} />
);

// test that the spy was called
expect(spy.callCount).to.equal(1);

这使得测试变得更加简单,更重要的是,您正在测试组件行为 - 而不是Redux。