繁体   English   中英

Jest with TypeScript (Backend - Node/Express) 说 Cannot use import statement outside a module

[英]Jest with TypeScript (Backend - Node/Express) says Cannot use import statement outside a module

我正在为 Node/Express TypeScript 后端进行 Jest 测试。 我最近了解了我正在实施的全局测试设置,以减少在所有测试文件中执行的类似变量和 function 调用。
因此,例如在下面的代码中,我想使 app 和 userToken 成为全局变量,并等待在测试设置文件中调用的 initDatabase() function。⬇

import initServer from '../initServer';
import { initDatabase } from '../util/databaseHandler';
import loginWithAWS from '../util/loginWithAWS';

const app = initServer();
let userToken: any;

describe(`Test on the GET method of route `, () => {

  beforeAll( async() => {
    try{
      await initDatabase();
      userToken = await loginWithAWS('userRole');
    }catch(error){
      return error;
    }
  });
});

但是,在使用变量和 function 实施全局测试设置后,然后通过命令yarn test在终端/bash/cmd 上运行测试,抛出此错误:⬇
抛出错误

抛出错误的正在进行的解决方案如下所示实现。 您的协助将受到高度重视。:
测试设置文件:
testSetup.ts

import initServer from '../initServer';
import { initDatabase } from '../util/databaseHandler';
import loginWithAWS from '../util/loginWithAWS';


const initializeTestingSetup = async function() {
  (global as any).app = initServer();
  await initDatabase();
  (global as any).userToken = await loginWithAWS('userRole');
};

module.exports = initializeTestingSetup;

下面是我的项目测试的笑话配置文件:
jest.config.js

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
  transform: {
    '^.+\\.ts$': 'ts-jest',
    '^.+\\.js$': 'babel-jest',
    '^.+\\.mjs$': 'babel-jest',
  },
  moduleDirectories: ['node_modules', '<rootDir>/src'],
  moduleNameMapper: {
    '@controllers/(.*)': '<rootDir>/src/controllers/$1',
    '@middleware/(.*)': '<rootDir>/src/middleware/$1',
    '@models/(.*)': '<rootDir>/src/models/$1',
    '@routes/(.*)': '<rootDir>/src/routes/$1',
    '@types/(.*)': '<rootDir>/src/types/$1',
    '@util/(.*)': '<rootDir>/src/util/$1',
  },
  globals: {
    'ts-jest' : {
      astTransformers: {
        before: [
          'ts-jest/dist/transformers/path-mapping'
        ]
      },
    } 
  },
  globalSetup: './src/__tests__/testSetup.ts',
};

我将衷心感谢您的帮助。

Jest 似乎在任何 globalSetup 脚本中都存在 ES6 导入语法问题。 我会尝试更改您的testSetup.ts脚本以使用require而不是import因此它不必是 ES6 模块。 请注意,您在testSetup.js中混合了 CommonJS 和 ES6/ESM 语法,因为您有import ,但使用module.exports 像这样的东西可能会起作用(这是未经测试的):

const initServer = require('../initServer');
const initDatabase = require('../util/databaseHandler');
const loginWithAWS = require('../util/loginWithAWS');


const initializeTestingSetup = async function() {
  (global as any).app = initServer();
  await initDatabase();
  (global as any).userToken = await loginWithAWS('userRole');
};

module.exports = initializeTestingSetup;

更新:如何尝试使 globalsetup 与 ESM 更兼容:

import initServer from '../initServer';
import { initDatabase } from '../util/databaseHandler';
import loginWithAWS from '../util/loginWithAWS';

export default async function setup() {
  (global as any).app = initServer();
  await initDatabase();
  (global as any).userToken = await loginWithAWS('userRole');
};

这有帮助吗?

确保package.json具有type: module集。 我使用的是 node14,所以我已经按照此处的建议将目标和库设置为es2020

用于测试的 tsconfig:

{
  "compilerOptions": {
    "allowUnreachableCode": false,
    "declaration": true,
    "target": "es2020",
    "lib": ["es2020"],
    "importHelpers": true,
    "incremental": true,
    "module": "es2020",
    "esModuleInterop": true,
    "moduleResolution": "Node",
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "target": "es2020"
  },
  "include": ["test"],
  "exclude": ["build", "node_modules"]
}

我设置esModuleInterop以避免默认导入可能出现的任何问题,并将module设置为es2020 (允许 import.meta 用于 __dirname)。

我们可以要求 jest 配置将模块视为 esm:

{
  "preset": "ts-jest",
  "testEnvironment": "node",
  "testMatch": ["<rootDir>/test/**/*.test.ts"],
  "rootDir": ".",
  "extensionsToTreatAsEsm": [".ts"],
  "globalSetup": "<rootDir>/test/setup.ts",
  "globals": {
    "ts-jest": "./tsconfig.tests.json"
  }
}

在您的全局设置中,坚持使用 esm 导出和导入:

import express from "express";
import bodyParser from "body-parser";
import morgan from "morgan";
import helmet from "helmet";
import cors from "cors";
import PicoDb from "picodb";

const app = express();

const logger = morgan("combined");

const jsonParser = bodyParser.json();
const queryParser = bodyParser.urlencoded({ extended: true });

app.use(logger);
app.use(helmet());

app.use(queryParser);
app.use(jsonParser);

app.use(cors());
app.options("*", cors());

export { app };

export default async function globalSetup() {
  const db = new PicoDb();
  await db.insertMany([{ a: 1 }, { a: 2, b: 2 }]);
  app.listen(3000, () => {
    console.log("Server listening on port 3000");
  });
}

这在我运行测试时按预期工作(开玩笑没有退出,因为我没有在拆卸步骤中关闭服务器)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM