Jest, Enzyme: Invariant Violation: You should not use <Route> or withRouter() outside a <Router>

Maryja Piaredryj picture Maryja Piaredryj · Apr 25, 2018 · Viewed 44.1k times · Source

I have a <UserListComponent /> which outputs one <Contact /> component and list of contacts presentated by <Contacts />.

The problem is that in the test for <UserListComponent /> when I try to mount it, test outputs an error Invariant Violation: You should not use <Route> or withRouter() outside a <Router>

withRouter() is used in <Contacts /> component.

How can I mock ContactsComponent without router in test of parent component?

I found some similar issue https://www.bountysource.com/issues/49297944-invariant-violation-you-should-not-use-route-or-withrouter-outside-a-router but it only describes situation when component is cover by withRouter() itself, not children.

UserList.test.jsx

const mockResp = {
  count: 2,
  items: [
    {
      _id: 1,
      name: 'User1',
      email: '[email protected]',
      phone: '+123456',
      online: false
    },
    {
      _id: 2,
      name: 'User2',
      email: '[email protected]',
      phone: '+789123',
      online: false
    },
    {
      _id: 3,
      name: 'User3',
      email: '[email protected]',
      phone: '+258369147',
      online: false
    }
  ],
  next: null
}

describe('UserList', () => {
  beforeEach(() => {
    fetch.resetMocks()
  });

  test('should output list of users', () => {
    fetch.mockResponseOnce(JSON.stringify(mockResp));

    const wrapper = mount(<UserListComponent user={mockResp.items[2]} />);

    expect(wrapper.find('.contact_small')).to.have.length(3);
  });

})

UserList.jsx

export class UserListComponent extends PureComponent {
  render() {
    const { users, error } = this.state;
    return (
      <React.Fragment>
        <Contact
          userName={this.props.user.name}
          content={this.props.user.phone}
        />
        {error ? <p>{error.message}</p> : <Contacts type="contactList" user={this.props.user} contacts={users} />}
      </React.Fragment>
    );
  }
}

Contacts.jsx

class ContactsComponent extends Component {
  constructor() {
    super();
    this.state = {
      error: null,
    };
  }

  render() {
    return (
      <React.Fragment>
        <SectionTitle title="Contacts" />
        <div className="contacts">
         //contacts
        </div>
      </React.Fragment>
    );
  }
}

export const Contacts = withRouter(ContactsComponent);

Answer

Edhar Dowbak picture Edhar Dowbak · May 25, 2018

To test a component (with Jest) that contains <Route> and withRouter you need to import Router in you test, not in your component

import { BrowserRouter as Router } from 'react-router-dom';

and use it like this

app = shallow(
    <Router>
        <App />
    </Router>);