测试未导出的TypeScript函数
在相关问题中可以看到,在StackOverflow上,关于在类或模块中测试私有函数的问题是一个受到广泛讨论的问题 - 以下可能是一个架构解决方案,甚至不需要讨论这个问题:
如果这些函数被认为足够重要,需要单独测试,但又不应该作为模块的一部分被访问,那么它们是否应该被放置在自己的模块中呢?
这将解决您的可访问性问题 - 它们现在是一个模块中的公共函数,您可以轻松地在另一个模块中使用它们,而不将它们作为该模块的一部分暴露出来。
以下是一个示例代码,演示了如何在TypeScript中测试未导出的函数:
// moduleA.ts export function publicFunction() { // public function logic... } function privateFunction() { // private function logic... } // moduleA.test.ts import * as ModuleA from './moduleA'; describe('ModuleA', () => { describe('publicFunction', () => { it('should work correctly', () => { // test publicFunction... }); }); describe('privateFunction', () => { it('should work correctly', () => { const result = ModuleA['privateFunction'](); // access privateFunction using bracket notation expect(result).toBe(expectedValue); }); }); });
通过将私有函数放在自己的模块中,我们可以在测试文件中使用模块导入来访问它们,并进行测试。这样一来,我们既可以将函数单独测试,又不会将它们作为模块的一部分暴露出来。
在TypeScript中,如果一个函数没有被导出,是无法直接访问的。然而,还是有一种“半隐藏”的方式可以导出这些函数,以下是一种可能的解决方法:
// 在你的库模块中,像平常一样声明内部函数为非导出的
function someInternalFunctionA(x: number): number {
return x;
}
function someInternalFunctionB(x: number): number {
return x;
}
// 在底部,提供一个公开的逃生通道,用于访问你希望在测试中可用的特定函数
export const _private = {
someInternalFunctionA,
someInternalFunctionB,
};
在测试代码中,你可以这样做:
import { _private } from "./myModule";
test("someInternalFunctionA", () => {
expect(_private.someInternalFunctionA(42)).toEqual(42);
});
这种方法的优点有:
- 不需要直接将someInternalFunctionA标记为导出项。
- 很明显,_private下的内容并不是官方的公共接口的一部分。
如果你正确地进行测试驱动开发,那么在生产环境中不应该运行仅用于测试目的的代码。除了具有误导性之外,这可能是潜在问题的源头。
当然,这并不是一个很好的解决方案,但从实用的角度来看:(1)导出私有符号的代码是一种非常小的形式的“在生产中运行用于测试的代码”,(2)在我实际参与的项目中,这从未引起过问题,(3)能够测试更精细的内部函数肯定有助于我们交付正确的代码。
测试 TypeScript 中未导出的函数的原因是无法访问非导出模块函数。为了解决这个问题,可以将函数分组到一个实用类中,并利用私有类成员可以通过方括号表示法访问的特性。
下面给出了一个例子来说明这个解决方法:
module MyModule { export class UtilityClass { private privateFunction() { alert("privateFunction"); } } } var utility = new MyModule.UtilityClass(); utility["privateFunction"](); // 弹出 "privateFunction"
在这个例子中,我们将私有函数 `privateFunction` 放到了一个实用类 `UtilityClass` 中。通过创建 `UtilityClass` 的实例,并使用方括号表示法访问私有函数,我们可以成功调用这个未导出的函数。
需要注意的是,私有函数的访问仍然会在编译器中生成错误,但是在运行时仍然能够成功调用。这种方式可能不符合 TypeScript 的设计初衷,因为私有函数应该是不可访问的。然而,这种方法提供了一种在特定情况下测试私有函数的可能性。