使用 TypeScript 使用 Jest 测试或模拟未导出的函数

ngf*_*ixl 5 unit-testing typescript jestjs

有没有办法使用 TypeScript 用 Jest 测试未导出的函数?我已经看到 SO 答案推荐了一些库,rewire但似乎它们还不是真正兼容 TypeScript。另一种方法是导出这些私有函数,但我认为必须有一个解决方案,而不只是为了测试目的而导出。

设置如下。有两种功能,一种是导出,一种不是。

export function publicFunction() {
  privateFunction();
}

function privateFunction() {
  // Whatever it does
}
Run Code Online (Sandbox Code Playgroud)

在我的单元测试中,我希望解决两种情况。测试privateFunction自身并模拟它进行publicFunction测试。

我在测试时使用ts-jest来编译打字稿文件。该jest.config.json模样

{
  "transform": {
    "^.+\\.(t|j)sx?$": "ts-jest"
  },
  "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(tsx?)$",
  "moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json", "node"],
  "testEnvironment": "node",
  "globals": {
    "ts-jest": {
      "tsConfig": "test/tsconfig.spec.json"
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我熟悉jest.fn()但我不知道如何覆盖或提取私有函数。并且单元测试将类似于

import { publicFunction } from '../src';

describe('publicFunction', () => {
  it('should call "privateFunction" once', () => {
    // Overwrite privateFunction with jest.fn();

    publicFunction();

    expect(...).toHaveBeenCalled(1);
  });
});
Run Code Online (Sandbox Code Playgroud)

或者测试私有函数,无法导入它。

import { privateFunction } from '../src/index'

describe('privateFunction', () => {
  it(...
});
Run Code Online (Sandbox Code Playgroud)

有什么想法或建议吗?谢谢!

Zak*_*med 7

为了使用 JEST 和 Typescript 测试非导出函数,我使用了 Rewire。我们必须重新连接 TS 构建文件夹的路径而不是 .ts 文件路径,这没什么问题。

以下是我的目录结构:

app
|---dist
    |---controllers
        |---api.js
    src
    |---controllers
        |---api.ts
        |---api.spec.ts
Run Code Online (Sandbox Code Playgroud)

所以对于重新布线,我必须提供路径./dist/controllers/api而不是 ./src/controllers/api

这是我的示例代码:

import rewire from "rewire";

const api = rewire('../../dist/controllers/api');   // path to TS build folder

describe("API Controller", () => {
    describe('Fetch Route Params', () => {

        let fetchRouteParams: (url: string) => string;

        beforeEach(() => {
            fetchRouteParams = api.__get__('fetchRouteParams'); // non-exported function
        });

        it('should fetch route params from url', () => {
            const url = "https://example.com/foo/api/products";
            expect(fetchRouteParams(url)).toEqual('foo/api/products');
        });

        it('should not fetch route params from url', () => {
            const url = "";
            expect(fetchRouteParams(url)).toEqual('');
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

即使我没有遇到一些更好的解决方案,除了 rewire. 但它适用于测试非导出函数。

我使用过的 NPM 包:

npm i -D rewire
npm i -D @types/rewire
Run Code Online (Sandbox Code Playgroud)

希望有帮助,谢谢。