Jest: Jest building runtime can instantiate a module twice when mocks reuse production utilities.

Created on 29 Mar 2018  路  1Comment  路  Source: facebook/jest

Do you want to request a _feature_ or report a _bug_?
Bug

What is the current behavior?
I have a module that connects to a database that I mock using jest. I also have a set of production utilities that uses a value exported from the database module. Finally, my mock implementation of the database module provides some test helpers by importing and using the production utilities.

Depending on the order in which I set up my imports I can get jest to build my mock module twice such that my test and my production utilities call two different versions of the mock. When that mock has a singleton instance (e.g. an in memory facade on a database) this means that I have two copies of the database making for very unexpected results (e.g. the utility writes to it's database but my test does not see any data written).

This happens specifically when the mock module is imported before the utilities which causes jest to then import the mock module again. It can be worked around by importing the utility before importing the mock module directly.

**If the current behavior is a bug, please provide the steps to reproduce and
See https://github.com/lewchuk/jest-import-bug. There are two test suites which have the same tests but a different import order. It also includes a console log of the stack trace when the mock module is imported. When it is broken the stack trace shows the double import:

at Object.<anonymous> (/Users/lewchuk/jest-import-bug/src/__mocks__/toBeMocked.js:5:14)
          at Runtime._execModule (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:448:13)
          at Runtime.requireMock (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:322:12)
          at Runtime.requireModuleOrMock (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:335:19)
          at Object.<anonymous> (/Users/lewchuk/jest-import-bug/src/utilUsingMock.js:1:1)
          at Runtime._execModule (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:448:13)
          at Runtime.requireModule (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:265:14)
          at Runtime.requireModuleOrMock (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:337:19)
          at Object.<anonymous> (/Users/lewchuk/jest-import-bug/src/__mocks__/toBeMocked.js:1:1)
          at Runtime._execModule (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:448:13)
          at Runtime.requireMock (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:322:12)
          at Runtime.requireModuleOrMock (/Users/lewchuk/jest-import-bug/node_modules/jest-runtime/build/index.js:335:19)
          at Object.<anonymous> (/Users/lewchuk/jest-import-bug/__tests__/testingUtil-broken.js:1:1)

What is the expected behavior?
When jest builds the runtime for a test suite it should only build a single instance of any imported module.

Please provide your exact Jest configuration
See linked github repo.

Run npx envinfo --preset jest in your project directory and paste the
results here

npx: installed 1 in 7.063s

  System:
    OS: macOS Sierra 10.12.6
    CPU: x64 Intel(R) Core(TM) i7-6567U CPU @ 3.30GHz
  Binaries:
    Node: 8.9.4
    Yarn: 1.5.1
    npm: 5.6.0
  npmPackages:
    jest:
      wanted: ^22.4.3
      installed: 22.4.3
Needs Triage

Most helpful comment

I've thought some more about this and understand that this issue is basically a circular dependency created by the mocking process. If this behavior is not something that jest wants to support, I think a reasonable alternative resolution would be for the jest runtime to throw an error when it encounters this situation so that people don't accidentally get into this situation, especially since static analysis tools like linters won't catch this import cycle.

>All comments

I've thought some more about this and understand that this issue is basically a circular dependency created by the mocking process. If this behavior is not something that jest wants to support, I think a reasonable alternative resolution would be for the jest runtime to throw an error when it encounters this situation so that people don't accidentally get into this situation, especially since static analysis tools like linters won't catch this import cycle.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ianp picture ianp  路  3Comments

StephanBijzitter picture StephanBijzitter  路  3Comments

gustavjf picture gustavjf  路  3Comments

hramos picture hramos  路  3Comments

stephenlautier picture stephenlautier  路  3Comments