1
votes

I have looked at the following tutorials https://hackernoon.com/unit-testing-redux-connected-components-692fa3c4441c https://airbnb.io/enzyme/docs/api/shallow.html and tried to create a shallow rendered test of a component but i have actions being triggered on render which collect data and help render the component. how can i mock this?

tests/jest/containers/homecontent.js

import configureStore from 'redux-mock-store'
import { shallow } from 'enzyme';
import { HomeContent } from '../../../app/containers/home';
const passMetaBack = meta => {
        this.setState({
            title: 'test',
            description: 'test'
        });
    };

// create any initial state needed
const initialState = {};
// here it is possible to pass in any middleware if needed into //configureStore
const mockStore = configureStore();

describe('Login Component', () => {
    let wrapper;
    let store;
    beforeEach(() => {
        // our mock login function to replace the one provided by mapDispatchToProps
        const mockLoginfn = jest.fn();
        //creates the store with any initial state or middleware needed
        store = mockStore(initialState)
        wrapper = shallow(<HomeContent isGuest={false} isReady={true} priv={{}} passMetaBack={passMetaBack} fetchContents={mockLoginfn} />)
    });

    it('+++ render the DUMB component', () => {
        expect(wrapper.length).toEqual(1)
    });
});

The error i get is

 FAIL  tests/jest/containers/homecontent.test.js
  Login Component
    ✕ +++ render the DUMB component (25ms)

  ● Login Component › +++ render the DUMB component

    TypeError: Cannot read property 'then' of undefined

      38 |              if(this.props.isReady && this.props.priv != undefined){
      39 |              let self = this;
    > 40 |              this.props.fetchContents()
      41 |              .then(response => {
      42 |                      let data = response.payload.data;
      43 |                      if (data.header.error) {

      at HomeContent.initData (app/containers/home.js:40:7)
      at HomeContent.render (app/containers/home.js:71:12)
      at ReactShallowRenderer._mountClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:195:37)
      at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:143:14)
      at node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:287:35
      at withSetStateAllowed (node_modules/enzyme-adapter-utils/build/Utils.js:103:16)
      at Object.render (node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:286:68)
      at new ShallowWrapper (node_modules/enzyme/build/ShallowWrapper.js:119:22)
      at shallow (node_modules/enzyme/build/shallow.js:19:10)
      at Object.<anonymous> (tests/jest/containers/homecontent.test.js:24:19)

  ● Login Component › +++ render the DUMB component

    TypeError: Cannot read property 'length' of undefined

      26 |
      27 |     it('+++ render the DUMB component', () => {
    > 28 |         expect(wrapper.length).toEqual(1)
      29 |     });
      30 | });
      31 |

      at Object.<anonymous> (tests/jest/containers/homecontent.test.js:28:24)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        2.218s
Ran all test suites matching /tests\/jest\/containers\/homecontent.test.js/i.

this.props.fetchContents() comes in from an action on the component

1

1 Answers

2
votes

mockLoginfn is used as this.props.fetchContents in the component. fetchContents is a function that returns a promise, whereas mockLoginfn is a jest mock function that doesn't return anything.

So, you need to provide a mock implementation for the mockLoginfn so it behaves like a promise. For example (using the code snippet above):

const mockLoginfn = jest.fn();
mockLoginfn.mockImplementation(() => Promise.resolve({
  payload: {
    data: {
      header: {
        error: 'some error'
      }
    }
  }
}));