babel-jest ES2015 import statements

2019-05-02 00:16发布

问题:

has anyone been writing jasmine / jest tests using es2015 syntax? how much shimming / polyfill / gerrymandering does it require?

i’m having trouble importing functions correctly. i have one module: …./utils/TweetUtils.js

'use strict';

export function getListOfTweetIds (tweets) {
  return Object.keys(tweets);
};

and one test suite:

…./__tests__/TweetUtils-test.js

'use strict';
jest.dontMock('../TweetUtils');
import * as TweetUtils from '../TweetUtils';

describe('Tweet utilities module', () => {

  it('has access to the TweetUtils methods', () => {

    let testObj = {a:'a',b:'b',c:'c'};
    // Passes
    expect(TweetUtils.getListOfTweetIds).toBeDefined();
    // Passes
    expect(typeof TweetUtils.getListOfTweetIds).toBe('function');
    // Fails
    expect(TweetUtils.getListOfTweetIds(testObj)).toBeTruthy();
  });
});

If I hack a console output into the suite with something like this:expect(‘’).toBe(TweetUtils);

Jasmine reports this:

- Expected: '' toBe: {
      default: {
          getListOfTweetIds: Function
      },
      getListOfTweetIds: Function
  }

So it seems like the import statement is doing something, but it’s clearly not importing my methods honestly. I get the same results when I import using the named function syntax: import {getListOfTweetIds} from ‘../TweetUtils’; But if I use the default syntax: import getListOfTweetIds from ‘../TweetUtils’; The second spec fails - it’s no longer typeof function, but typeof object // => {default: Function}

I’ve been combing the docs and open-issues. There’ve been related issues for a few months, but the known issues don’t seem right. I’ve tried importing my jest.dontMock statements to avoid hoisting, circa: https://github.com/babel/babel-jest/issues/16 but no dice.

Everything works if I modify TweetUtils.js to use module.exports = function… and bring it into the suite using const myFunction = require(‘../TweetUtils’), but it doesn’t feel like I’m channeling the true ES2015 magic. Is everyone just dealing with wonky work-arounds right now while the ecosystem catches up to the new syntax?

回答1:

As you said, import statements are hoisted and it causes problems with the jest auto-mocking feature (the module is imported before you tell jest to unmocked it).

TweetUtils.getListOfTweetIds is correctly imported but it's mocked, so each calls return undefined. That's why the third expectation fails.

Importing jest.dontMock statement could work (I tested it) but it sounds dirty to me (do you really want to create a "dontmock module" file for each test modules ?)

You have to use the require syntax for the tested module. Replace

import * as TweetUtils from '../TweetUtils';

by

const TweetUtils = require('../TweetUtils');

It was the same in jest example before I fixed it : jest#379



回答2:

The issue seems to be with babel and not with jest . Try this solution.

If you are using 'create-react-app' then install these dev dependencies:

"babel-cli": "^6.26.0",
"babel-jest": "^22.4.1",
"babel-preset-react-app": "^3.1.1",

And also update the .babelrc (create this file if it doesn't exist ) :

{
"presets": [
    "@babel/preset-env",
    "@babel/preset-react"
      ]
}

And now both jest and npm test both work as they should.