如何使用打字稿在玩笑测试之间重置测试主题?

Mon*_*Ben 4 unit-testing typescript jestjs

我正在使用打字稿和玩笑。我正在尝试执行一个非常简单的单元测试,但它总是失败。这是我的代码:

// init.ts
let initialized = false;
let secretName: string;

export function init(name: string) {
    if (initialized) {
        throw new Error("Cannot re-initialize.");
    }

    secretName = name;

    initialized = true;
}

export function getSecret(): string {
    return secretName;
}
Run Code Online (Sandbox Code Playgroud)
// init.test.ts
describe("init", () => {
    async function getTestSubject() {
        return await import("./init");
    }

    it("should set the secret name properly", async () => {
        const init = await getTestSubject();
        init.init("bruce wayne");
        expect(init.getSecret()).toEqual("bruce wayne");
    });

    it("should throw an exception if initialized more than once", async () => {
        const init = await getTestSubject();

        const callInit = function() {
            init.init("bruce wayne");
        };
        callInit();
        expect(callInit).toThrowError("Cannot re-initialize.");
    });
});
Run Code Online (Sandbox Code Playgroud)

第二个单元测试由于抛出异常而失败。当第一次调用“callInit()”时,这应该是该单元测试第一次调用 init 。然而,在考虑两个单元测试时,这是第二次调用它。

我认为通过在每个测试中动态导入测试主题(例如“./init”),我可以避免这个问题,因为我最初尝试在顶部导入 init ,如下所示:

import {init, getSecret} from "./init";
Run Code Online (Sandbox Code Playgroud)

关于如何测试这个有什么想法吗?我认为这是一个非常基本的测试用例,所以要么开玩笑有很大的限制,要么我只是错过了一些明显的东西......

谢谢!

Zac*_*ten 5

我可以通过调用jest.resetModules()a来使其工作beforeEach(),以便在每次测试之前重置模块名称空间。

let initModule

beforeEach(() => {
  jest.resetModules()
  initModule = require('./init')
})

it('should set the secret name properly', () => {
  initModule.init('bruce wayne')
  expect(initModule.getSecret()).toEqual('bruce wayne')
})

it('should throw an exception if initialized more than once', () => {
  const callInit = () => initModule.init('bruce wayne')
  callInit()
  expect(callInit).toThrowError('Cannot re-initialize.')
})

Run Code Online (Sandbox Code Playgroud)

您是正确的,这里有必要内联导入其他模块,因为不可能使用标准 ES6 导入来完成模块名称空间的重置。但在上面的例子中,我使用了我认为更简单的require()方法来做到这一点。

如果您正在使用 typescript 并且仍然希望强类型initModule,您仍然可以使用标准 ES6 导入来导入它以获取类型。

import * as InitModule from './init'

let initModule: typeof InitModule
Run Code Online (Sandbox Code Playgroud)