When a Jest test imports a module that includes:
// src/__tests__/test.js
import '../index.js'
// src/index.js
export * from './something';
// src/something.js
export function dog() { console.log('hello this is dog'); }
Jest will blow up with
FAIL __tests__/test.js
Runtime Error
TypeError: Cannot redefine property: __esModule
at Function.defineProperty (native)
The reason for this is that Jest's mocking is slightly inaccurate, and this interacts badly with Babel's module system.
A Babel ES6 module defines:
// build/stuff.js
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.dog = dog;
function dog() {
console.log('hello this is dog');
}
export * from './stuff' is implemented as:
// build/index.js
Object.keys(_stuff).forEach(function (key) {
if (key === "default") return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function get() {
return _stuff[key];
}
});
});
In Node this is fine, because Object.keys(_stuff) return ["dog"]
However when you're collecting the object props, you don't keep track if it's enumerable.
You first get the slots with getSlots():
> getSlots(component)
< ["__esModule", "dog"]
But when collecting the metadata with getMetadata() only the property value is considered. The property descriptor is ignored.
So for __esModule, we get:
> mockMetadata.members.__esModule
Object
type: "constant"
value: true
and thats gets placed in the mock.
At this point, Object.keys(_stuff) returns ["__esModule", "dog"], which causes the redefine error.
Related to issue #872
Until this is fixed I recommend unmocking the other module in question. Personally I would probably always recommend explicitly listing everything a module exports if you'd like to iterate over them but this should still work with Jest.
Great bug report, @tals! I was banging my head against this, and didn't realize that it's got to do with Jest mocking: https://github.com/coopy/esmodule-dupe-definition/
I will unmock my problematic module in question.
Another workaround till this is fixed is to create a mock file:
// src/__tests__/test.js
import '../index.js'
// src/index.js
export * from './dog';
export function cat() { console.log('hello this is cat'); }
// src/dog.js
export function dog() { console.log('hello this is dog'); }
// src/__mocks__/index.js
module.exports = {
...jest.genMockFromModule('../index'),
...jest.genMockFromModule('../dog')
};
@lennerd, I tried your example (exactly identical, except root dir is app/ instead of src/), and it fails

using Jest CLI v13.2.3, jasmine2, babel-jest
@Fandekasp What version of Babel do you use?
I'm using [email protected] and [email protected]
Woah, I didn't realize babel-jest would even work with babel 5. We don't really support it any more…
Yes, maybe thats the reason. I use [email protected] and [email protected].
It looks like react-native 0.23.1 doesn't support babel 6... We'll have to upgrade our repo to get jest tests work with export.
Thank you for your super fast support!
This will be fixed in the next release this week. Sorry about the issue.
Has there been a release that fixed it?
Still seeing this issue with this type of module
plugins/index.js
import * as logger from './loggerPlugin';
import * as webApi from './webApiPlugin';
export {
logger,
webApi,
};
It's consumed like this:
import * as plugins from './plugins'`
// plugins.__esModule is enumerable although commonjs transform is NOT in loose mode
For now I have to use this mock as a workaround(which also triggers duplicate mocks warning, but that's another issue).
plugins/__mocks__/index.js
const _ = require('lodash');
const source = require.requireActual('../index');
const fixedSource = _.omit(source, '__esModule');
// See https://github.com/facebook/jest/issues/880
Object.defineProperty(fixedSource, '__esModule', {
value: true,
});
module.exports = fixedSource;
I'm also seeing issues with this for jest 21.1.0 and babel-jest 21.0.2, the solution of disableAutomock and unmock have no effect:
index.test.js
jest.disableAutomock();
jest.unmock('ui');
import {Button} from 'ui';
node_modules/ui/index.js
export {default as Icon} from './icons/components/icon';
./node_modules/jest/bin/jest.js ./index.test.js
FAIL index.test.js
● Test suite failed to run
TypeError: Cannot redefine property: Icon
at Function.defineProperty (native)
at Object.<anonymous> (node_modules/ui/index.js:4:198)
at Object.<anonymous> (index.test.js:13:187)
at next (native)
at next (native)
at process._tickCallback (internal/process/next_tick.js:103:7)
Looks like some are still having issues with this like, do we want to re-open this issue or create a new one? I'll try to help and submit a solution.
I'm still having these errors. Has there been a fix?
The latest versions of babel-jest and... everything else worked for me. Try bumping versions, I’ll try to give you definite versions when I get back in.
The issue still exists.
Ideally this should be reopened.
@le0nik mind opening up a new issue with a reproduction?
I am also still facing the issue, I guess this needs to be reopened.
No it doesn't, you're encountering a separate issue. The issue in the OP does not reproduce anymore. Please create a new issue including a reproduction
You are right, I was thinking that this issue is the cause while in the end I just had a recursive re-export. Probably many people still complaining on this issue have had the same problem.
These things are really difficult to debug in Jest and I wonder if anything can be done about that, maybe a feature request is in order.
Most helpful comment
I'm also seeing issues with this for
jest21.1.0andbabel-jest21.0.2, the solution ofdisableAutomockandunmockhave no effect:index.test.js
node_modules/ui/index.js
./node_modules/jest/bin/jest.js ./index.test.js