javascript - 在 React/Redux 中测试连接的组件

标签 javascript reactjs redux react-redux jestjs

我正在尝试测试我的 React/Redux 应用程序的连接组件,我编写了一些测试用例,它实际上抛出了错误:

App component › shows account info and debits and credits`

Invariant Violation: Could not find "store" in either the context or props of "Connect(AccountInfo)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(AccountInfo)".

引发错误app.test.js的测试用例如下。我的问题是我不明白我应该通过 Connect() 在这里包装什么,因为我在这里没有使用 AccountInfo :

import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import App from './App';
import * as actions from '../../actions';

function setup() {
  const props = {
    errorMessage: null,
    actions
  };

  const enzymeWrapper = mount(<App {...props} />);

  return {
    props,
    enzymeWrapper,
  };
}

describe('App component', () => {
  it('shows account info and debits and credits`', () => {
    const {enzymeWrapper} = setup();
    expect(enzymeWrapper.find('.account-info').exists()).toBe(true);
    expect(enzymeWrapper.find('.debits-and-credits').exists()).toBe(true);
  });

  it('shows error message', () => {
    const {enzymeWrapper} = setup();
    enzymeWrapper.setProps({ errorMessage: 'Service Unavailable' });
    expect(enzymeWrapper.find('.error-message').exists()).toBe(true);
  });
});

我的containers/app.js:

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as actions from '../actions';
import AppComponent from '../components/App/App';

const mapStateToProps = state => ({
  isFetching: state.balance.isFetching,
  errorMessage: state.errorMessage,
});

const mapDispatchToProps = dispatch => ({
  actions: bindActionCreators(actions, dispatch),
});

const AppContainer = connect(mapStateToProps, mapDispatchToProps)(AppComponent);

export default AppContainer;

组件app.js:

import React, { Component } from 'react';
import ErrorMessage from '../../containers/ErrorMessage';
import AccountInfo from '../../containers/AccountInfo';
import DebitsAndCredits from '../../containers/DebitsAndCredits';
import './App.css';

const AppComponent = () =>
  <div className="app">
    <AccountInfo />
    <DebitsAndCredits />
  </div>;

export class App extends Component {
  componentWillMount() {
    const { actions } = this.props;
    actions.fetchBalance();
  }

  render() {
    const { errorMessage } = this.props;
    return errorMessage ? <ErrorMessage /> : <AppComponent />;
  }
}

export default App;

更新:

我更新了我的测试用例,现在看起来像:

import React from 'react';
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import createSagaMiddleware from 'redux-saga';
import { initialState } from '../../reducers/balance/balance';
import App from './App';
import * as actions from '../../actions';

const middlewares = [createSagaMiddleware];
const mockStore = configureMockStore(middlewares);
const store = mockStore(initialState);

function setup() {
  const props = {
    errorMessage: null,
    actions,
  };

  const enzymeWrapper = mount(
    <Provider store={store}>
      <App {...props} />
    </Provider>
  );

  return {
    props,
    enzymeWrapper,
  };
}

describe('App component', () => {
  it('shows account info and debits and credits`', () => {
    const { enzymeWrapper } = setup();
    expect(enzymeWrapper.find('.account-info').exists()).toBe(true);
    expect(enzymeWrapper.find('.debits-and-credits').exists()).toBe(true);
  });

  it('shows error message', () => {
    const { enzymeWrapper } = setup();
    enzymeWrapper.setProps({ errorMessage: 'Service Unavailable' });
    expect(enzymeWrapper.find('.error-message').exists()).toBe(true);
  });
});

我现在的错误是:

App component › shows account info and debits and credits`

    TypeError: Cannot read property 'account' of undefined

UPD 2:

我在创建模拟商店时放置的initialState:

const initialState = {
  isFetching: false,
  account: {},
  currency: '',
  debitsAndCredits: [],
};

我的AccountInfo组件:

import React from 'react';

const AccountInfo = ({ account, currency }) =>
  <header className="account-info">
    <p>{account.name}</p>
    <p>
      IBAN: {account.iban}<br />
      Balance: {account.balance}<br />
      Currency: {currency}<br />
    </p>
  </header>;

export default AccountInfo;

最佳答案

为了测试连接的组件,您还需要模拟提供者,因为连接从 redux 存储中选择状态变量。

这样做

const enzymeWrapper = mount (<Provider store={mockStore}><App {...props}/></Provider>)

您还需要模拟 redux 存储。

编辑1:

只需查看您的 AccountInfo 组件,它就会告诉我您正在此处的 props 中期待帐户。

AccountInfo = ({account}) =>

这意味着 App.js 必须在 props 中传递帐户的值。货币也是如此。

关于javascript - 在 React/Redux 中测试连接的组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44707530/

相关文章:

javascript - Redux——繁重的工作应该在哪里发生——reducer、action、容器还是表示组件?

javascript - 在 React.js 中覆盖/扩展 ES7 类的静态属性

javascript - React向组件添加 "undefined"类

typescript - 使用 Typescript 测试 redux 异步操作

arrays - 无法将文件放入 redux 数组

javascript - 服务器响应状态为 404 () - 加载资源失败

javascript - 根据浏览器缩放更改 css

javascript - Redux 在功能组件中分派(dispatch)后没有立即更新

php - 如何从 jquery serializearray() 检索 $_POST 变量

javascript - 我如何将 Json 数据发布到我的状态 ReactJs 中