首页 > 解决方案 > 如何使用 react-i18next 测试有状态的、redux 连接的组件

问题描述

我处于需要对也连接到 redux 存储的有状态组件进行单元测试以调度事件的情况。我正在使用 Jest 和 Enzyme。

我已经尝试了文档中提供的各种示例: https ://react.i18next.com/misc/testing

这些示例都没有涵盖使用 redux-connect 的用例。

考虑以下伪代码中的反应组件:

// ../MyComponent.js

import React, { Component } from 'react';
import { bindActionCreators, compose } from 'redux';
import { connect } from 'react-redux';
import { withNamespaces } from 'react-i18next';

class MyComponent extends Component {
  constructor(props) {
    super(props);
    // init state…
  }
  // Code body…
}

// Using compose from Redux lib
export default compose(
  connect(null, mapDispatchToProps),
  withNamespaces('myNamespace'),
)(MyComponent);

单元测试:

// ../__tests__/MyComponent.test.js

import React from 'react';
import { shallow, mount } from 'enzyme';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import { I18nextProvider } from 'react-i18next';

import i18n from '../../i18nForTests';
import reducers from '../../reducers';
import MyComponent from '../MyComponent';

const createStoreWithMiddleware = applyMiddleware()(createStore);

let MyComponentForTest = (
  <Provider store={createStoreWithMiddleware(reducers)}>
    <I18nextProvider i18n={i18n}>
      <MyComponent />
    </I18nextProvider>
  </Provider>
);

describe('MyComponent state', () => {
    let myPage;
    test('init', () => {
      myPage = shallow(MyComponentForTest); <-- Not getting the actual component.
    });
});

使用以下依赖项

"react": "^16.6.1",
"react-app-polyfill": "^0.1.3",
"react-dev-utils": "^6.0.5",
"react-dom": "^16.6.1",
"react-i18next": "^8.3.8",
"react-inlinesvg": "^0.8.2",
"react-redux": "^5.1.1",
"redux": "^4.0.1",
"i18next": "^12.1.0",
"identity-obj-proxy": "3.0.0",
"jest": "23.6.0",
"jest-pnp-resolver": "1.0.1",
"jest-resolve": "23.6.0",
"webpack": "4.19.1",
"enzyme": "^3.7.0",
"enzyme-adapter-react-16": "^1.7.0",

当使用来自 Enzyme的shallowmount函数时,我无法检索实际组件。相反,我得到了包装的上下文,无论是提供者、上下文对象还是其他东西——这意味着我无法测试组件。

澄清一下——这是我在添加 react-i18next 库之前的单元测试的样子……</p>

在 MyComponent.js 中导出

export default connect(null, mapDispatchToProps)(MyComponent); <-- Note, not using compose as it is not needed.

单元测试,MyComponent.test.js

let MyComponentForTest = <MyComponent store={createStoreWithMiddleware(reducers)} />;

describe(’MyComponent', () => {
  describe('initially', () => {
    let myPage;

    test('init', () => {
      myPage = shallow(MyComponentForTest).dive(); <-- Note, using dive(), to get the component.
      console.log('*** myPage: ', myPage.debug());
    });
});

在终端:

<MyComponent store={{...}} redirectPage={[Function]} />

因此,当不使用react-i18next时,我显然能够获取组件。

我认为至少部分问题是withNamespaces()不返回组件,而是将其包装在某种上下文对象中......

标签: reactjsreduxjestjsi18nextreact-i18next

解决方案


好吧,我在这里的建议是导出MyComponent并将其作为道具传递模拟状态。像这样的东西:

const mockedState = {
    ...state data you want to pass
}

const MyComponentForTest = <MyComponent state={mockedState} />


describe('MyComponent state', () => {
    let myPage;
    test('init', () => {
      myPage = shallow(MyComponentForTest);
    });
});

这里的重点是,您的组件在传递的某个状态下的行为方式是您想要在此处测试的。这应该在这里达到目的。


推荐阅读