jest: jest.spyOn(module, 'method', 'get') failed as method not declared configurable
This seems to be an edge case around mocking or spyOn a module built with Babel, while it may be related to babel module export settings, but would like to get some insights here first to see if there’s anything I’ve missed or anything we can do on Jest side.
deps versions:
"babel-cli": "^6.26.0",
"babel-core": "^6.26.3",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-env": "^1.7.0",
"jest": "^23.5.0",
Had a depedency dep-package
built with babel with the following .babelrc:
{
"presets": [
[
"env", { "targets": { "node": "6.1.0" } }
]
],
"plugins": [
"transform-object-rest-spread"
]
}
in test.js
import * as depPackage from 'dep-package';
jest.mock('dep-package');
module mocks would work
import * as depPackage from 'dep-package';
depPackage.compose = jest.fn();
import * as depPackage from 'dep-package';
jest.spyOn(depPackage, 'compose');
this would throw error TypeError: Cannot set property compose of [object Object] which has only a getter
import * as depPackage from 'dep-package';
jest.spyOn(depPackage, 'compose', 'get');
this would throw error compose is not declared configurable
Not sure what is causing the difference between module mock with jest.mock() and manual mock =jest.fn() here?
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 24
- Comments: 20 (2 by maintainers)
@zhenyulin give a try with this,
jest.mock('dep-package', () => ({ ...jest.requireActual('dep-package'), })); const cwpDetectionAgency = require('dep-package');
instead of doing
import * as depPackage from 'dep-package';
This has helped me, any thing which is out side of the current code base we have to do this.
Finally I got this. It’s an unrobust, but working solution, that monkey-patches
Object.defineProperty
in the setup file.In
setupTests.js
:In tests helpers:
in tests:
May be it will help someone. Also this
unfreezeImport
method can be united with the patcheddefineProperty
insetupTests.js
file.I’ll use the Bug Report template here.
🐛 Bug Report
jest.mock('dep-package')
works well, while manual mocking throwTypeError: Cannot set property compose of [object Object] which has only a getter
, and spyOn ‘get’ throw erroris not declared configurable
To Reproduce
clone this repo: https://github.com/Financial-Times/n-express-monitor
in src/tests/operation.js
add the module mock, manual mock and spyOn code as shown in the initial post
Expected behavior
get
shouldn’t throw an error, or if it indicates some limitation from how package is produced here, would be great to have some note in the docs somewhereLink to repl or repo (highly encouraged)
https://github.com/Financial-Times/n-express-monitor
Run
npx envinfo --preset jest
Paste the results here:
https://twitter.com/slicknet/status/782274190451671040
Feel free to send a PR if you want to see this fixed
if you have this error with
jest
andmobx
this answer might help you https://github.com/mobxjs/mobx/issues/1867#issuecomment-518987737Thanks @AnilGayakwad! that worked for me, a whole working example would look something like this:
@faiwer You have no idea how much this has helped. I have been trying to fix a testing helper w/ a spyon function that is used in ~300 tests. Bc it’s a helper function, I couldn’t replace it with
mock
like everyone has been suggesting. You saved my life lol.ModuleMockerClass._spyOnProperty
throws that error if:configurable
descriptor of the target propery isfalse
Also I started unfreezing all es6-like exports automatically. I intercept each
defineProperty
invocation, check that it looks like es6-export-like object, and make itconfigurable: true
. After thatjest.spyOn
and any other similar mechanisms work.But if you wanna do the same in your codebase you need to take into consideration that it’s a dirty hack that can potentially break something else. E.g.:
defineProperty
resultexport let mutableValue
(it’s fixable, but with more efforts)IMHO it still worths it. Because the only way I see to make it “properly” is to use real DI everywhere. Or just don’t write tests.