如何使用酶测试嵌套的连接组件?

时间:2018-05-03 08:43:57

标签: javascript reactjs redux jestjs enzyme

我正在尝试测试嵌套的连接组件(Redux已连接): Main组件具有Container组件,由App中的store wrapper提供。

import React, { Component } from 'react';
import Main from './components/Main';
import './App.css';
import { Provider } from 'react-redux'
import createStore from './redux'
import applyConfigSettings from './config'

// Apply config overrides
applyConfigSettings()

const store = createStore()

class App extends Component {
  render() {

    return (
      <Provider store={store}>
          <Main/>
      </Provider>

    );
  }
}

export default App;

Main.js

import React, { Component } from 'react';
import logo from '../logo.svg';
import { connect } from 'react-redux'

import Container from './Container'

export class Main extends Component {

    render(){
        return (
            <div className="App">
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <h1 className="App-title">Welcome to Pomodoro App</h1>
                </header>
                <Container/>
            </div>
        );
    } 
}

const mapStateToProps = (state) => {
    return {
      fetching: state.user.fetching,
    }
  }

  const mapDispatchToProps = (dispatch) => {
    return {

    }
  }

  export default connect(mapStateToProps, mapDispatchToProps)(Main)

Container.js

import React, { Component } from 'react';
import Grid from 'material-ui/Grid';
import { connect } from 'react-redux'


export class Container extends Component{
    render(){
        return (
            <div className="grid-root">

            </div>
        )
    }
}

const mapStateToProps = (state) => {
    return {
      fetching: state.user.fetching,
    }
  }

  const mapDispatchToProps = (dispatch) => {
    return {

    }
  }

  export default connect(mapStateToProps, mapDispatchToProps)(Container)

所有这些都是使用Create-react-app库创建的。我也安装了酶进行测试。这是我的Main.test.js测试文件

import React from 'react';

import { shallow, mount } from 'enzyme';

import {Main} from '../../components/Main'
import ContainerConnect, {Container} from '../../components/Container';

import configureStore from 'redux-mock-store';
import { Provider, connect} from 'react-redux';

describe('Main', () => {
    let wrapper;
    let mountWrapper;
    it('wraps all the contents in a div with .App class', () => {
        wrapper = shallow(<Main />);
        expect(wrapper.find('.App').length).toEqual(1);
    });

    it('wraps content of header in a div with .App-header class', () => {
        wrapper = shallow(<Main />);
        expect(wrapper.find('.App-header').length).toEqual(1);
    });

    it('mount', () => {
        const middlewares = [];
        const mockStore = configureStore(middlewares);
        const initialState = {}
        const store = mockStore(initialState)
        mountWrapper = mount(
            <Provider store={store}>
                    <Main />
            </Provider>
        );
    });

  })

我上次测试时出现以下错误:

 FAIL  src/tests/components/Main.test.js
  ● Console

    console.error node_modules/react-dom/cjs/react-dom.development.js:9643
      The above error occurred in the <Connect(Container)> component:
          in Connect(Container) (at Main.js:16)
          in div (at Main.js:11)
          in Main (at Main.test.js:31)
          in Provider (created by WrapperComponent)
          in WrapperComponent

      Consider adding an error boundary to your tree to customize error handling behavior.
      Visit some link to fb to learn more about error boundaries.

  ● Main › mount

    TypeError: Cannot read property 'fetching' of undefined

      at Function.mapStateToProps [as mapToProps] (src/components/Container.js:18:30)
      at mapToPropsProxy (node_modules/react-redux/lib/connect/wrapMapToProps.js:54:92)
      at Function.detectFactoryAndVerify (node_modules/react-redux/lib/connect/wrapMapToProps.js:63:19)
      at mapToPropsProxy (node_modules/react-redux/lib/connect/wrapMapToProps.js:54:46)
      at handleFirstCall (node_modules/react-redux/lib/connect/selectorFactory.js:37:18)
      at pureFinalPropsSelector (node_modules/react-redux/lib/connect/selectorFactory.js:85:81)
      at Object.runComponentSelector [as run] (node_modules/react-redux/lib/components/connectAdvanced.js:43:25)
      at Connect.initSelector (node_modules/react-redux/lib/components/connectAdvanced.js:195:23)
      at new Connect (node_modules/react-redux/lib/components/connectAdvanced.js:136:15)
      at constructClassInstance (node_modules/react-dom/cjs/react-dom.development.js:6801:20)
      at updateClassComponent (node_modules/react-dom/cjs/react-dom.development.js:8336:9)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:8982:16)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:11814:16)
      at workLoop (node_modules/react-dom/cjs/react-dom.development.js:11843:26)
      at renderRoot (node_modules/react-dom/cjs/react-dom.development.js:11874:9)
      at performWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:12449:24)
      at performWork (node_modules/react-dom/cjs/react-dom.development.js:12370:9)
      at performSyncWork (node_modules/react-dom/cjs/react-dom.development.js:12347:5)
      at requestWork (node_modules/react-dom/cjs/react-dom.development.js:12247:7)
      at scheduleWorkImpl (node_modules/react-dom/cjs/react-dom.development.js:12122:13)
      at scheduleWork (node_modules/react-dom/cjs/react-dom.development.js:12082:12)
      at scheduleRootUpdate (node_modules/react-dom/cjs/react-dom.development.js:12710:5)
      at updateContainerAtExpirationTime (node_modules/react-dom/cjs/react-dom.development.js:12738:12)
      at Object.updateContainer (node_modules/react-dom/cjs/react-dom.development.js:12765:14)
      at ReactRoot.Object.<anonymous>.ReactRoot.render (node_modules/react-dom/cjs/react-dom.development.js:16069:15)
      at node_modules/react-dom/cjs/react-dom.development.js:16488:14
      at Object.unbatchedUpdates (node_modules/react-dom/cjs/react-dom.development.js:12557:12)
      at legacyRenderSubtreeIntoContainer (node_modules/react-dom/cjs/react-dom.development.js:16484:17)
      at Object.render (node_modules/react-dom/cjs/react-dom.development.js:16543:12)
      at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:218:50)
      at new ReactWrapper (node_modules/enzyme/build/ReactWrapper.js:98:16)
      at mount (node_modules/enzyme/build/mount.js:19:10)
      at Object.it (src/tests/components/Main.test.js:29:42)
          at new Promise (<anonymous>)
      at Promise.resolve.then.el (node_modules/p-map/index.js:46:16)
          at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:118:7)

测试嵌套连接组件是否如此困难?我必须在应用程序中继续使用更多它。这也意味着测试按钮点击,所有更难以测试?

1 个答案:

答案 0 :(得分:0)

根据您要测试的内容,您根本不必处理redux。

由于您正在测试 XMLResource res = XMLResource .load(new StringReader("<html><head><style>@page { size : 29.7cm 21cm; }</style></head><body></body></html>")); 组件以及是否正确呈现标题,因此只需完全模拟您的<Main />

<Container />

然后你可以浅登你的jest.mock('../../components/Container', () => ()=> <div id="mockContainer"> mockContainer </div>); 而不用担心还原。

之后,当您开始对<Main />进行单元测试时,只需对React.Component类进行单元测试,而不必担心连接的组件,测试它是多余的。

换句话说,您应该能够测试任何React应用程序,而无需模拟redux存储。只是完全模拟连接组件。

More info here