Testing ES6 class with Jest throws 'not a constructor' error

UnknownDeveloper picture UnknownDeveloper · Oct 1, 2018 · Viewed 11.3k times · Source

I found a similar problem here, but there doesn't seem to be an answer.

I'm trying to test an ES6 class using Jest, like so:

// src/myclass.js
export default class MyClass {
    constructor(options) {
        // currently this is empty while I debug this problem
    }
}

and the test:

// test/myclass.test.js
import { MyClass } from '../src/myclass.js';

describe("Test Constructor", () => {

    test("doesn't throw error when constructed", async () => {
        expect(() => {
            const testMyClass = new MyClass();
        }).not.toThrowError();
    }

});

When I run the test, Jest throws an error saying:

TypeError: _myClass.MyClass is not a constructor

My best guess is that this is an issue with the babel config, but I can't seem to figure it out. If I change MyClass to a function instead of a class and drop the export/import (i.e., the pre-class way of doing things) then it works as expected.

Here's my config in package.json:

"devDependencies": {
    "@babel/core": "^7.1.2",
    "@babel/preset-env": "^7.1.0",
    "babel-core": "^7.0.0-bridge.0",
    "gulp": "^3.9.1",
    "gulp-babel": "^8.0.0",
    "gulp-jest": "^4.0.2",
    "gulp-rename": "^1.4.0",
    "gulp-uglify": "^3.0.1",
    "jest": "^23.6.0",
    "jest-cli": "^23.6.0",
    "pump": "^3.0.0",
    "regenerator-runtime": "^0.12.1"
  },
  "babel": {
    "presets": [
      "@babel/preset-env"
    ]
  },
  "jest": {
    "testPathIgnorePatterns": [
      "<rootDir>/node_modules/",
      "<rootDir>/test/._*.test.js"
    ],
    "testEnvironment": "jsdom",
    "setupFiles": [
      "<rootDir>/src/myclass.es6.js"
    ]
  }

Answer

CRice picture CRice · Oct 1, 2018

Your import and export syntaxes do not match. You'll need to change one or the other for this to work. If you want to use the default export, eg:

export default class MyClass { ... }

Then the corresponding import is:

import MyClass from '../src/myclass.js'

Or if you'd like to continue using the same import syntax, then remove the 'default' when exporting:

export class MyClass { ... }

Then:

import { MyClass } from '../src/myclass.js'