jest: Mock defined in __mocks__ directory not being used in submodules
I have a file named app.js
. Immediately adjacent to that I have a manual __mocks__/app.js
file. I have a test that both requires this app
module and requires a module that has an export function that requires this app
module when called (only happens at runtime, it’s not a circular dependency issue).
I have attached an isMock: true
property to my manual mock. Here is the other submodule I am including in my test:
exports.obj = function() {
var app = require('./app/app');
console.log("Is this a mock in my submodule: " + app.isMock);
console.log(app);
}
I then run my test. I require('../../app/app.js')
from my test, and print the isMock
property on it and it shows as true, and thus is being mocked correctly there. However, it is logging the unmocked version of app
from the above submodule when the test is run. The only way I resolved this issue was by doing jest.setMock('../../app/app.js', require('../../app/__mocks__/app.js'))
in my test. When I do this, the mock is properly being used directly in my test file and in my submodule in the test file.
Am I doing something wrong? The docs are very unclear as to the use of the __mocks__
folder, there is only one mention of it. I am fairly certain this is unintended behaviour, the file in the __mocks__
folder should be used across and inside all modules in my test.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 20
- Comments: 19 (3 by maintainers)
Commits related to this issue
- UICIRCLOG-34 Make global __mocks__ be used in submodules see https://github.com/facebook/jest/issues/335#issuecomment-703691592 — committed to folio-org/stripes-acq-components by axelhunn 4 years ago
- UICIRCLOG-34 Make global __mocks__ be used in submodules (#390) see https://github.com/facebook/jest/issues/335#issuecomment-703691592 — committed to folio-org/stripes-acq-components by axelhunn 4 years ago
I recommend using jest.mock(‘path/to/module/name’, () => {…}) for this. I don’t think we’ll add support for nested manual mock files.
This behavior feels odd to me. Wouldn’t it make sense for
__mocks__
to be used all the time in replacement for the actual module, even without the requirement of telling jest to do so? I thought of the mocks in the__mocks__
folder as some kind of global replacement. Limiting the scope of these mocks as discussed here seems broken.A way to use
__mocks__
as a global replacement I stumbled upon is to define such mocks in thejest.setup.js
file like so:This certainly requires us to re-define each mock in the
__mocks__
directory but is a nice combination of being able to define global mocks of a file and defining the actual mock in a dedicated file close to the real module.@benadamstyles That only works if you’re using the mocked module directly in test. It doesn’t work when the mocked module is a dependency of a different module that is the one under test. In that case, the dependency won’t use its
__mocks__
file when called from the module under test.@cpojer I really like jest, but the documentation around manual mocking seems to be a sore point in a lot of github issues. I’d love to help, but the behaviour is too cryptic. I agree with @MattyKuzyk that it seems counterintuitive that a module under test wouldn’t use a manual mock defined for a dependency when the test explicitly says to
jest.mock
that module.Conversely, a manually mocked node_modules dependency IS used when it is called in a module under test, where no
jest.mock
is needed.http://facebook.github.io/jest/docs/en/jest-object.html#jestmockmodulename-factory-options
I found this while searching through the docs. My guess is that is also the official way of thinking with these nested submodules and manual mocking. Maybe this will help clarify for some people, maybe not. Hoping it’s helpful to someone.
I have been having this problem and found this comment, which solved it for me. It should be in the docs.
I found a way to implement the desired behaviour by adding the below to a setup file:
Is it expected that this works
and this doesn’t?
I thought they should be equivalent from the mocking perspective.
I’d love to be able to reuse mocks without having to write them in every test that needs the mocked code, but there doesn’t seem to be an easy way of doing so. It’s possible that I’m missing something here.
For the ones researching, the way I solved my problem: (Want to define only 1 mock, to be used in all my tests) was to import all my mocks into
setupTests.ts
file.This allowed me to centralize the definition of my mocks for all my testing for easier maintenance. I agree with previous commenters that the
__mocks__
behavior is poorly defined in the documentation. It took me many hours of trial and errors and mind-boggling confusion to get to a working solutionWe aren’t currently investing in improvements to the mock system heavily. If you’d like to work on this please join us on discord (#jest on reactiflux) and I’m happy to help you get a PR ready 😃