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.definePropertyin the setup file.In
setupTests.js:In tests helpers:
in tests:
May be it will help someone. Also this
unfreezeImportmethod can be united with the patcheddefinePropertyinsetupTests.jsfile.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 configurableTo 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
getshouldn’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 jestPaste 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
jestandmobxthis 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
mocklike everyone has been suggesting. You saved my life lol.ModuleMockerClass._spyOnPropertythrows that error if:configurabledescriptor of the target propery isfalseAlso I started unfreezing all es6-like exports automatically. I intercept each
definePropertyinvocation, check that it looks like es6-export-like object, and make itconfigurable: true. After thatjest.spyOnand 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.:
definePropertyresultexport 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.