首页 > 解决方案 > 如何使用 jasmine-node 对非模块进行单元测试?(与关闭 Electron 中的节点集成有关)

问题描述

我有点进退两难。

我打开contextIsolation并关闭nodeIntegration了我的BrowserWindow并加载了一个本地 html 页面。(正如 Electron 推荐的那样)。

这个本地 html 页面需要一个 node 模块,这会导致崩溃,因为 Electron 无法在窗口中加载 node 模块,因为 node 被禁用:

main.ts:

import { app, BrowserWindow } from "electron";
import * as path from "path";

function createWindow() {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, "preload.js"),
    },
  });

  mainWindow.loadFile(path.join(__dirname, "../index.html"));
  mainWindow.webContents.openDevTools();
}

(async () => {
  await app.whenReady();
  createWindow();
})();

app.on("window-all-closed", () => {
  if (process.platform !== "darwin") {
    app.quit();
  }
});

索引.html:

<body>
  <h1>Hello World!</h1>
  <script src="./renderer.js"></script>
</body>

渲染器.js:

export interface A { }

未捕获的 ReferenceError:未在 renderer.js:2 中定义导出

崩溃的具体行是这样的:

Object.defineProperty(exports, "__esModule", { value: true });由于该export声明而存在。

在这种情况下,我可以删除导出(并且只需在需要它的其他模块中重新定义接口),但是我无法对我的脚本进行单元测试。

我目前正在jasmine-node用于单元测试,并且我一直需要我想在顶部测试的模块:

import * as Renderer from "./renderer"

这在 VSCode 中出现了一些关于如何Renderer不是模块的错误。

似乎需要工作(我猜 Node 可以require是非模块?),但这会导致 IIFE 在我的间谍设置​​之前运行。

如果Renderer是一个模块,我会这样做:

<script>
   require("renderer.js").main();
</script>

然后我的单元测试会在调用 main 方法之前在模块上设置间谍。但是由于我禁用了 Node,所以我不能require在我的 index.html 中,我必须内联加载脚本,所以我需要某种 IIFE 来替换 main 方法:

(async () => {
   await doSomething();
})();

然后如何使用 Jasmine 对这个非模块进行单元测试?

标签: node.jsunit-testingjasmineelectronjasmine-node

解决方案


我的解决方案最终变得很糟糕。

首先,我必须使我的非模块成为一个模块,以便我可以在我的规范中导入它。

我导出了我的界面并添加了一个 main 方法:

export interface A { }
export async function main(): Promise<void> {
    await doSomething();
}

为了避免我之前在禁用 Node 的情况下加载脚本时遇到的崩溃,我将这个 hack 添加到我的 html 页面:

<script>var exports = {};</script> // mutes the "exports not defined" error
<script src="./renderer.js"></script>

然后,如果 jasmine 没有运行,我让我的 IIFE 调用我的主要方法。

(async () => {
    if (!window.jasmine) {
        main();
    }
})();

我的单元测试同时设置了间谍并调用导出的 main 方法。


推荐阅读