Skip to content

Mock promises silently fail when created outside of the test scope #13132

@MaddyGuthridge

Description

@MaddyGuthridge

Describe the bug

As per this StackOverflow post, it appears that CRA has resetMocks enabled by default for testing.

While I understand this design decision, as it improves test quality, it also means that anyone who doesn't read the source code for CRA will be unaware of this change (given that it is not documented).

As such, you can run into extremely confusing behaviour where tests work when run directly with jest but fail due to the silent resetting of the mocks between tests when run with react-scripts test.

This behaviour is extremely confusing, especially given the lack of documentation, and so steps should be taken to make users aware of it. I think the most reasonable solution is to give a warning to users when they create a mock function in the global scope, and link them to some documentation on the changes that CRA has made to Jest's default behaviour (which will need to be created).

Did you try recovering your dependencies?

N/A

Which terms did you search for in User Guide?

  • Mock function
  • resetMocks
  • Testing
  • Promise testing

Environment

⋙   npx create-react-app --info

Environment Info:

  current version of create-react-app: 5.0.1
  running from /home/migue/.npm/_npx/c67e74de0542c87c/node_modules/create-react-app

  System:
    OS: Linux 6.2 Fedora Linux 37 (Workstation Edition)
    CPU: (12) x64 Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
  Binaries:
    Node: 19.1.0 - ~/.nvm/versions/node/v19.1.0/bin/node
    Yarn: 1.22.19 - ~/.nvm/versions/node/v19.1.0/bin/yarn
    npm: 9.6.5 - ~/.nvm/versions/node/v19.1.0/bin/npm
  Browsers:
    Chrome: Not Found
    Firefox: 112.0.1
  npmPackages:
    react: ^17.0.2 => 17.0.2 
    react-dom:  17.0.2 
    react-scripts: 5.0.1 => 5.0.1 
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

Add a test as follows:

const mockPromise = jest.fn().mockResolvedValue('example');

test('mock promise resolves', async () => {
  const result = await mockPromise();
  expect(result).toStrictEqual('example');
});

Expected behavior

The test would run normally (see output when running Jest directly), or I would be given a clear error message informing me of what my mistake was.

⋙ npx jest src/components/example.test.ts
 PASS  src/components/example.test.ts
  ✓ mock promise resolves (2 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.305 s
Ran all test suites matching /src\/components\/example.test.ts/i.

Actual behavior

When run with react-scripts test, it appears that the mock function completely failed.

⋙ npm t -- src/components/example.test.ts

> frontend@0.1.0 test
> react-scripts test --watchAll=false src/components/example.test.ts

 FAIL  src/components/example.test.ts
  ✕ mock promise resolves (3 ms)

  ● mock promise resolves

    expect(received).toEqual(expected) // deep equality

    Expected: "example"
    Received: undefined

      4 | test('mock promise resolves', async () => {
      5 |   const result = await mockPromise();
    > 6 |   expect(result).toEqual('example');
        |                  ^
      7 | });
      8 |

      at Object.<anonymous> (src/components/example.test.ts:6:18)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.93 s, estimated 1 s
Ran all test suites matching /src\/components\/example.test.ts/i.

Reproducible demo

See above for test case.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions