8

I have a CRA app and am trying to the use the manual mocks feature of Jest, but my manual mocks does not seem to be applied.

I use a base url of src (by setting it in tsconfig.json). Simplified, I have and have a file structure of

src/
|- components/
|-- Foo/
|--- index.js
|--- Foo.jsx
|- App.js
|- App.test.js

where App.js uses import Foo from "components/Foo". In App.test.js I want Foo to be mocked (it's computationally heavy and tested in unit tests). So in my test I added jest.mock("components/Foo") and in my desperation added several __mocks__ folders like

__mocks__
|- components\
|-- Foo.jsx
src/
|- __mocks__/
|-- components/
|--- Foo.jsx
|- components/
|-- Foo/
|--- __mocks__
|---- Foo.js
|--- index.js
|--- Foo.jsx
|- App.js
|- App.test.js

where each manual mock contains

console.log("Mock imported");

export default function MyMock(){
  console.log("Mock used");
  return <p />;
}

However, when running the tests no there are no console printouts from the mock and although Foo is assigned an empty mock, it does not use the intended manual mock.

What have I done wrong?

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Johan Book
  • 153
  • 1
  • 3
  • 10
  • can you share test file as well? also, just making sure, you are having relative path in ```jest.mock()```, right? like ```import SoundPlayer from './sound-player'; jest.mock('./sound-player'); // SoundPlayer is now a mock constructor``` – Sergey Semashko Dec 12 '20 at 04:57
  • No, I use absolute paths, both inside `App.js` and `App.test.js`. Is that what might be causing the problems? Using relative paths is difficult as I am working on a very large application – Johan Book Dec 15 '20 at 08:12

2 Answers2

1

Creating mock is a 3 step process:

  1. In App.js import Foo from 'components/Foo' imports Foo/index.js. Inside components create __mocks__/Foo/index.js and export mock component.
  2. Create a setup file for jest in project root jest.setup.js and declare jest.mock('src/components/Foo')
  3. In jest config, add option setupFilesAfterEnv: ['./jest.setup.js']
Johan Book
  • 153
  • 1
  • 3
  • 10
Achal Jain
  • 309
  • 1
  • 7
  • I put the `__mocks__` folder directly inside the `Foo` folder with an `index.js` inside `__mocks__`, then it worked as intended. – Johan Book Dec 15 '20 at 08:54
  • Yes, the file path for mock file inside mocks directory should match exactly with parent directory. – Achal Jain Dec 16 '20 at 13:36
0

I see that your file structure is incorrect. The __mocks__ directory should immediately under components

src/
|- components/
|-- Foo.js 
|-- __mocks__
|--- Foo.jsx
|- App.js
|- App.test.js

Now Foo.js on main module directory can be something like this

function Foo() {
    return (
     
       <h1> Foo</h1>
    );
  }

  export default Foo;

And __mocks/Foo.js can be

console.log("Mock imported");

function Foo() {
    return (
     
       <h1> Mock</h1>
    );
  }

  export default Foo;

App.test.js will contain jest.mock call

import { render, screen } from '@testing-library/react';
import App from './App';


jest.mock("./components/Foo");

test('renders learn react link', () => {

 
  render(<App />);
  const linkElement = screen.getByText(/Mock/i); // Check that MOCK component is called
  expect(linkElement).toBeInTheDocument();
});

See the git repository for working sample https://github.com/meera/jest_mock

Meera Datey
  • 1,913
  • 14
  • 15
  • Thanks for the repo. However, how should it be treated if `Foo` is a folder containing an `index.js` and a `Foo.jsx` file? `index.js` contains `export {default} from "./Foo";` – Johan Book Dec 15 '20 at 08:38
  • I realized that `__mocks__` should be inside the `Foo` folder and contain an `index.js` file. Then it works as intended – Johan Book Dec 15 '20 at 08:57
  • @JohanBook you're saying there needs to be a `src/components/Foo/__mocks__/index.js` file? – peterlawless Dec 17 '20 at 16:23
  • I updated the repository - It should work even if Foo is a folder containing an index.js and Foo.jsx file. – Meera Datey Dec 18 '20 at 04:46