TypeError:_API.default 不是带有 Jest 测试的构造函数

Cec*_*uez 5 javascript reactjs jestjs react-native expo

我有一个 API 类,我试图在 React 应用程序中使用它。

// API file

class API {
...
}

export default API;

// Other file
import API from "utils/API";

const api = new API();
Run Code Online (Sandbox Code Playgroud)

我收到错误:

TypeError: _API.default is not a constructor
Run Code Online (Sandbox Code Playgroud)

但是..好像我的默认值已设置?

我的 Jest 设置是这样的:

  "jest": {
    "setupFiles": [
      "./jestSetupFile.js"
    ],
    "testEnvironment": "jsdom",
    "preset": "jest-expo",
    "transformIgnorePatterns": [
      "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg|react-router-native/.*|@invertase/react-native-apple-authentication/.*)"
    ]
  },
Run Code Online (Sandbox Code Playgroud)

强烈猜测这是由于我的 babel、webpack 或 package.json 的配置造成的。

可能是什么原因造成的?

注意,我想澄清一下,这在我的主应用程序中不会发生,只会在 Jest 测试中发生


如果我将其更改为命名导出/导入,我会得到以下结果:

TypeError: _API.API is not a constructor
Run Code Online (Sandbox Code Playgroud)

极其令人困惑的行为。

Jos*_*shA 17

正如其他人所提到的,看到一个最小的可重复示例会很有帮助。

然而,还有另一个可能的原因。您是否在模拟测试文件中的 API 类?如果一个类被错误地模拟为“对象”而不是函数,有时会发生此问题。不能使用“new”运算符实例化对象。

例如,假设我们有一个类文件,utils/API如下所示:

class API {
  someMethod() {
    // Does stuff
  }
}

export default API;
Run Code Online (Sandbox Code Playgroud)

以下是模拟此类的“不正确”方法,TypeError... is not a constructor如果在创建模拟后实例化该类,则会抛出错误。

import API from 'utils/API';

jest.mock('utils/API', () => {
  // Returns an object
  return {
    someMethod: () => {}
  };
})

// This will throw the error
const api = new API();
Run Code Online (Sandbox Code Playgroud)

以下代码会将类模拟为函数,并接受new运算符并且不会抛出错误。

import API from 'utils/API';

jest.mock('utils/API', () => {
  // Returns a function
  return jest.fn().mockImplementation(() => ({
    someMethod: () => {}
  }));
})

// This will not throw an error anymore
const api = new API();
Run Code Online (Sandbox Code Playgroud)


小智 7

尝试添加"esModuleInterop": true,您的tsconfig.json. BY 默认esModuleInterop设置为 false 或不设置。B 将 esModuleInterop 设置为 true 会更改编译器的行为并修复一些 ES6 语法错误。请参阅此处的文档。


Emi*_*ile 5

我添加此内容是因为我提出的问题相同,但设置略有不同。

我没有默认导出该类,即

MyClass.ts

// with default
export default MyClass {
   public myMethod()
   {
      return 'result';
   }
}

// without default, which i'm doing in some instances.
export MyClass {
   public myMethod()
   {
      return 'result';
   }
}

Run Code Online (Sandbox Code Playgroud)

当您没有默认值时,导入语法会发生变化。

在(开玩笑的)测试中,如果你遵循你确实有的惯例export default MyClass(){};

然后进行以下工作。

const MOCKED_METHOD_RESULT = 'test-result'
jest.mock("MyClass.ts", () => {
    // will work and let you check for constructor calls:
    return jest.fn().mockImplementation(function () {
        return {
            myMethod: () => {
                return MOCKED_METHOD_RESULT;
            },
   
        };
    });
});
Run Code Online (Sandbox Code Playgroud)

但是,如果您没有并且default或者正在尝试模拟其他类等,那么您需要执行以下操作。

请注意,这{get MyClass(){}}是关键部分,我相信您可以将其替换jest.fn().mockImplementation()jest.fn(()=>{})

jest.mock("MyClass.ts", () => ({
    get MyClass() {
        return jest.fn().mockImplementation(function () {
            return {
               myMethod: () => {
                   return MOCKED_METHOD_RESULT;
               },
   
           };
        });
    },
}));
Run Code Online (Sandbox Code Playgroud)

所以问题是您访问模拟类内容的方式。该get部分允许您正确定义类导出。


Cec*_*uez 4

这最终是由于我从中导出类的文件内有额外的代码。

import { store } from "root/App";

if (typeof store !== "undefined") {
  let storeState = store.getState();
  let profile = storeState.profile;
}
Run Code Online (Sandbox Code Playgroud)

在顶部,在我的班级之外,我一直在研究一些功能。

这导致类默认导出失败,但仅限于 Jest,而不是我的实际应用程序。