【问题标题】:Redux: How to test a connected component?Redux:如何测试连接的组件?
【发布时间】:2016-12-24 16:44:39
【问题描述】:

我正在使用Enzyme 对我的 React 组件进行单元测试。我知道为了测试原始的未连接组件,我必须将其导出并测试它(我已经这样做了)。我已经设法为连接的组件编写了一个测试,但我真的不确定这是否是正确的方法,以及我究竟想为连接的组件测试什么。

Container.jsx

import {connect} from 'react-redux';
import Login from './Login.jsx';
import * as loginActions from './login.actions';

const mapStateToProps = state => ({
  auth: state.auth
});
const mapDispatchToProps = dispatch => ({
  loginUser: credentials => dispatch(loginActions.loginUser(credentials))

});
export default connect(mapStateToProps, mapDispatchToProps)(Login);

Container.test.js

import React from 'react';
import {Provider} from 'react-redux';
import {mount, shallow} from 'enzyme';
import {expect} from 'chai';
import LoginContainer from '../../src/login/login.container';
import Login from '../../src/login/Login';


describe('Container Login', () => {
  it('should render the container component', () => {
    const storeFake = state => ({
      default: () => {
      },
      subscribe: () => {
      },
      dispatch: () => {
      },
      getState: () => ({ ...state })
    });
    const store = storeFake({
      auth: {
        sport: 'BASKETBALL'
      }
    });

    const wrapper = mount(
      <Provider store={store}>
        <LoginContainer />
      </Provider>
    );

    expect(wrapper.find(LoginContainer).length).to.equal(1);
    const container = wrapper.find(LoginContainer);
    expect(container.find(Login).length).to.equal(1);
    expect(container.find(Login).props().auth).to.eql({ sport: 'BASKETBALL' });
  });
});

【问题讨论】:

    标签: unit-testing reactjs redux enzyme


    【解决方案1】:

    正如您所指出的,我通常这样做的方式是导出未连接的组件,并对其进行测试。

    export {Login};
    

    这是一个例子。 Source of the componentsource of the tests

    对于封装的组件,我不编写测试,因为我的映射(mapStateToPropsmapDispatchToProps)通常非常简单。如果我想测试一个包装的组件,我真的只是在测试那些地图。所以我会选择明确地测试这些,而不是重新测试包装形式的整个组件。

    有两种方法可以测试这些功能。一种方法是在模块本身中导出函数。

    即;

    export {mapStateToProps, mapDispatchToProps}

    我不是这个的超级粉丝,因为我不希望应用程序中的其他模块访问它们。在我的测试中,我有时使用babel-plugin-rewire 来访问“范围内”变量,所以在这种情况下我会这样做。

    这可能看起来像:

    import {
      Login, __Rewire__
    }
    
    const mapStateToProps = __Rewire__.__get__('mapStateToProps');
    
    describe('mapStateToProps', () => { ... });
    

    【讨论】:

    • 我已经做到了。 import Login from ../login 是未连接的组件。我没有使用 {Login} 的原因是它们位于不同的文件中。
    • 另外,我究竟需要为容器组件测试什么?
    • mapStateToPropsmapDispatchToProps 怎么样?可以举个例子吗?
    • 更新了答案@umair。让我知道这是否有帮助。
    • 为了测试它们,我个人一直遵循导出mapStateToPropsmapDispatchToPropsmergeProps 的模式。我不知道babel-plugin-rewire 是一个选项 - 我得试一试。
    【解决方案2】:

    这是一个有趣的问题。

    我通常会同时导入容器和组件来进行测试。对于我使用的容器测试,redux-mock-store。组件测试用于测试异步功能。例如,在您的情况下,登录过程是使用 sinon 存根的异步函数。这是一个相同的sn-p,

    import React from 'react';
    import {Provider} from 'react-redux';
    import {mount, shallow} from 'enzyme';
    import {expect} from 'chai';
    import LoginContainer from '../../src/login/login.container';
    import Login from '../../src/login/Login';
    import configureMockStore from 'redux-mock-store';
    import thunk from 'redux-thunk';
    import { stub } from 'sinon';
    
    const mockStore = configureMockStore([thunk]);
    
    describe('Container Login', () => {
      let store;
      beforeEach(() => {
        store = mockStore({
          auth: {
            sport: 'BASKETBALL',
          },
        });
      });
      it('should render the container component', () => {
        const wrapper = mount(
          <Provider store={store}>
            <LoginContainer />
          </Provider>
        );
    
        expect(wrapper.find(LoginContainer).length).to.equal(1);
        const container = wrapper.find(LoginContainer);
        expect(container.find(Login).length).to.equal(1);
        expect(container.find(Login).props().auth).to.eql({ sport: 'BASKETBALL' });
      });
    
      it('should perform login', () => {
        const loginStub = stub().withArgs({
          username: 'abcd',
          password: '1234',
        });
        const wrapper = mount(<Login
          loginUser={loginStub}
        />);
      wrapper.find('button').simulate('click');
      expect(loginStub.callCount).to.equal(1);
      });
    });
    

    【讨论】:

    • 对 mapStateToProps 和 mapDispatch 的测试就足够了吗?
    • 是的。。你必须用覆盖工具检查,你会发现它被完全覆盖了
    • 实际我想知道的基本上是我们要测试容器/智能组件时要测试什么?
    • 你做过集成测试吗?我一直在做单元测试,但我读过我们也应该编写集成测试。如果是,我有一个重要问题可以分享链接
    • 不完全是我基本上安装组件并模拟事件并断言它..但这可能会给你一个更好的主意skillsmatter.com/skillscasts/…
    【解决方案3】:

    如果我们遇到路由器问题,可以考虑将路由器库添加到测试文件中,例如:

    import React from 'react';
    import { Provider } from 'react-redux';
    import { BrowserRouter as Router } from 'react-router-dom';
    import { mount } from 'enzyme';
    import ReadDots from './ReadDots';
    
    const storeFake = state => ({
      default: () => {
      },
      subscribe: () => {
      },
      dispatch: () => {
      },
      getState: () => ({ ...state })
    });
    
    const store = storeFake({
      dot: {
        dots: [
          {
            id: '1',
            dot: 'test data',
            cost: '100',
            tag: 'pocket money'
          }
        ]
      }
    });
    
    describe('<ReadDots />', () => {
      it('should render ReadDots component', () => {
        const component = mount(
          <Provider store={store}>
            <Router>
              <ReadDots />
            </Router>
          </Provider>
        );
        expect(component.length).toEqual(1);
      });
    });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-29
      • 2017-11-26
      • 1970-01-01
      • 1970-01-01
      • 2021-02-03
      • 2016-05-09
      • 1970-01-01
      相关资源
      最近更新 更多