Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid "TypeError: Cannot set property" error with jest and babel v7?

Tags:

babeljs

jestjs

I have a project to be upgraded from babel v6 to babel v7. To make it work is not hard, but I met some problems in unit testing code.

For working code foo.js like below.

import foo from './bar';
export {foo};

When I try to mock it in unit testing code.

import * as Foo 'path/to/foo.js';
Foo.foo = jest.fn().mockReturnValue('whatever');

It fails with error:

TypeError: Cannot set property foo of #<Object> which has only a getter

It turns out that babel v7 do transpilation different from v6. It compiles foo.js into:

"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
Object.defineProperty(exports, "foo", {
  enumerable: true,
  get: function get() {
    return _bar.default;
  }
});

Since foo is defined as a getter-only property of exports, it cannot manipulate the exported foo any more.

For the time being, I just change foo.js to avoid such transpilation. I'm wondering whether this is any babel config to disable such transpilation. Any ideas?

like image 683
Morgan Cheng Avatar asked Jul 10 '18 03:07

Morgan Cheng


1 Answers

In Babel 7, you can disable this behaviour by enabling "loose" mode in @babel/preset-env. If you only want this behaviour for your test environment, you can further scope the configuration in your babelrc/babel.config.js.

babel.config.js

module.exports = {
    env: {
        production: {
            presets: [
                [
                    '@babel/preset-env',
                    { loose: false },
                ],
            ],
        },
        test: {
            presets: [
                [
                    '@babel/preset-env',
                    { loose: true },
                ],
            ],
        },
    },
}

See loose transformation.

like image 58
noahnu Avatar answered Oct 18 '22 11:10

noahnu