I came across this weird error when trying to test some React components.

Test suite failed to run

Invariant Violation: You must pass a component to the function returned by connect. Instead received undefined

The structure is very simple, there is a Redux container wrapping a React presentational component with local state.

// Container component

const mapStateToProps = ...

const mapDispatchToProps = ...

export default connect (
    mapStateToProps,
    mapDispatchToProps
)(Container);
// Component

export default class Component extends React.Component {
    constructor(props) {
        super(props);
        
        this.state = {
            foo: null
        };
        
        ...
    }
        
    render() {
        return (
            <div>Component</div>
        );
    }
}

I wrote tests for both of the files above, the container tests ran fine. However, when I try to run the following test in Jest I get the above error.

I checked my container's connect() function, but everything looks fine. After doing a little research, other people mentioned their issues were caused by one of the following issues:

  • Circular dependencies between components
  • Wrong usage of export and export default then imported the wrong way
  • Used the connect function wrongly, passed the wrong parameters

I checked against all these points, but none of it applies to the code I was working with.

What's even more strange is that I could build and run the web app no problem. So this problem seems to only exist in Jest.

So I decided to do more debugging around it, "when stuck, trial and error" right? I commented out the line which does the rendering, which looked something like this:

it(('should not fail') => {
    // const wrapper = shallow(<Component />);

    expect(true).toBe(false);
});

This test obviously failed, and it actually ran the test suite. Which is a good news, because I was never getting this far before. The fact the rendering is failing must mean my export was done right, or something related to it. So I went back and checked again, and same as before I found nothing.

I tried commenting back all the shallow render and commented the import at the top of the file (see below). This also ran the test suite giving me the error that Component is undefined.

// import Component from './Component';

it(('should not fail') => {
    const wrapper = shallow(<Component />);
});

The issue

It turns out the problem was still circular dependency, but the shared dependency was something really stupid. Let me explain.

I am using Typescript, I declared a type a few levels higher and then imported it in Component. This made that entire high level component dependency of Component, thus causing the circular dependency.

As suspected it was a simple fix, but I had to go through so many loops. For anyone getting this error, check the 3 points mentioned above because I think they will cover 99.99% of the cases.

Also note to self:

  1. Circular dependency doesn't get picked up by Typescript in React/Redux project. This could be a limitation of webpack or my webpack config, as when I used Typescript with rollup.js it did pick up circular dependency.
  2. Typescript will build React app with Circular dependency, but it won't run the test suite

The real life example

Here is the exact error I got so people can compare to see if they have the same problem. SpendPointsMenu in this case is the Component in my example above, and SpendPointsMenuContainer is obviously the container. Spend is the high level component where I was importing the type from. Don't worry too much about SpendPoints it just sits in between Spend and SpendPointsMenuContainer.

Test suite failed to run

Invariant Violation: You must pass a component to the function returned by connect. Instead received undefined

      26 | )(SpendPointsMenu);
      27 |

      at invariant (node_modules/invariant/invariant.js:40:15)
      at wrapWithConnect (node_modules/react-redux/lib/components/connectAdvanced.js:101:29)
      at Object.<anonymous> (src/views/spend/spendPoints/SpendPointsMenuContainer.tsx:28:141)
      at Object.<anonymous> (src/views/spend/spendPoints/SpendPoints.tsx:13:33)
      at Object.<anonymous> (src/views/spend/Spend.tsx:16:46)
      at Object.<anonymous> (src/views/spend/spendPoints/SpendPointsMenu.tsx:20:40)
      at Object.<anonymous> (src/views/spend/spendPoints/SpendPointsMenu.test.tsx:7:461)

My first clue should have been:

SpendPointsMenu.tsx is causing an error in SpendPointsMenu.test.tsx, that's fine because that's the file I trying to test. But why is Spend.tsx causing an error in SpendPointsMenu.tsx.

I over looked this clue, and ended up spending hours trying to fix something very simple.