prismo
prismo

Reputation: 1899

Manual Mock Module Used By Components

I have several components that make use of a single hook useParams. The jest docs suggest using jest.mock to replicate this hook. As you can imagine, writing this mock over the space of several files could get annoying and as such I am seeking to make use of manual mocks. Jest docs suggest I create a __mocks__ directory adjacent to the file I'll be mocking - the file in this case being react-router-dom.js in node_modules. I have followed the directions of the docs and yet my tests are still failing because they cannot find useParams defined anywhere. An example:

src/components/compOne.js :

import React from 'react'
import styled from 'styled-components'
import { useParams } from 'react-router-dom'

const Wrapper = styled.div``

export default function CompOne() {
    const { id = '123' } = useParams()
    return (
        <Wrapper>
            <h2>{`ID: ${id}`}</h2>
        </Wrapper>
    )
}

src/__tests__/compOne.js :

import React from 'react'
import CompOne from '../components/compOne.js'
import { shallow } from 'enzyme'

jest.mock('react-router-dom')

test('renders without crashing', () => {
    shallow(<CompOne />)
})

root/__mocks__/react-router-dom.js :

jest.mock('react-router-dom', () => {
    useParams: () => ({
        id: 'MOCKED_VALUE',
    })
})

This is how the tests fail:

src/__tests__/compOne.js
  ● renders without crashing

    TypeError: (0 , _reactRouterDom.useParams) is not a function

       6 |
       7 | export default function CompOne() {
    >  8 |     const { id } = useParams()
         |                            ^
       9 |     return (
      10 |         <Wrapper>
      11 |             <h2>{`ID: ${id}`}</h2>

      at CompOne (src/components/navigator/pages/compOne.js:8:28)
      at ReactShallowRenderer.render (node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:829:32)
      at fn (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:645:55)
      at withSetStateAllowed (node_modules/enzyme-adapter-utils/src/Utils.js:99:18)
      at Object.render (node_modules/enzyme-adapter-react-16/src/ReactSixteenAdapter.js:645:20)
      at new ShallowWrapper (node_modules/enzyme/src/ShallowWrapper.js:411:22)
      at shallow (node_modules/enzyme/src/shallow.js:10:10)
      at Object.<anonymous> (src/__tests__/compOne.js:8:5)

If you're wondering about the structure of the project, please refer to the typical structure of create-react-app - with myapp/ being root/

Any help would be much appreciated. Thank you in advance!

Upvotes: 0

Views: 740

Answers (1)

domhabersack
domhabersack

Reputation: 431

The setup of your files is good. In your mock of react-router-dom, you’ll want to export an object that contains what you want the mock to have instead of calling jest.mock.

This is what you need to do in your /__mocks__/react-router-dom.js:

module.exports = {
  useParams: () => ({
    id: 'MOCKED_VALUE',
  })
}

Because you’re not mocking a core module of Node, you don’t need to call jest.mock at all. You can remove jest.mock('react-router-dom') from your test file.

Upvotes: 1

Related Questions