测试未导出的 TypeScript 函数
Testing TypeScript function which is not exported
我使用 Mocha/Chai 测试 JavaScript 前端代码,现在我们切换到 TypeScript。我有几个要测试的功能。但它们不应该是可导出的。我可以访问这个函数并在不添加 export
的情况下对其进行测试吗?
But they shouldn't be exportable. Can I get an access to this functions and test it without adding export to them?
一般来说,不会。可以访问私有 class 成员,但不能访问模块的未导出成员。
我会附和@Katana314 的评论——单元测试不应与非public 方法有关。尝试这样做表明您正在测试模块的实现细节,而不是模块声称要实现的合同。
正如您在相关问题中看到的,类 或模块内部测试私有函数的问题在 Whosebug 上引起了激烈的争论——以下可能是一种甚至没有讨论的架构解决方案:
如果这些功能足够重要,需要单独测试,但不应作为模块的一部分访问,是否应该将它们放在自己的模块中?
这将解决您的可访问性问题 - 它们现在是一个模块中的 public 函数,您可以轻松地从另一个模块中使用它们,而不是将它们作为该模块的一部分公开。
这完全是黑客攻击,但是嘿...
window.testing = {};
然后在你的模块中:
module.exports = {
myPublicFunction: myPublicFunction
};
window.testing.myModule = {
myPublicFunction: myPublicFunction,
myPrivateFunction: myPrivateFunction
};
无法访问未导出的模块函数。
module MyModule {
function privateFunction() {
alert("privateFunction");
}
}
MyModule.privateFunction(); // Generates a compiler error
但是,撇开私有方法测试的有效性问题不谈,您可以做的是。
将您的函数分组到实用程序 class 中,然后利用可以通过方括号表示法访问私有 class 成员这一事实。
module MyModule {
export class UtilityClass {
private privateFunction() {
alert("privateFunction");
}
}
}
var utility = new MyModule.UtilityClass();
//utility.privateFunction(); Generates a compiler error
utility["privateFunction"](); // Alerts "privateFunction"
我找到的最佳解决方案是以不同的名称导出私有函数,这样这个名称会提醒您不要在其他任何地方使用此函数。
export const getPrice__test = getPrice;
function getPrice(): number {
return 10 + Math.Random() * 50;
}
虽然无法直接访问未导出的函数,但仍有一种方法可以以“半隐藏”的方式导出它们。一种可能的方法是:
// In your library module declare internal functions as non-exported like normal.
function someInternalFunctionA(x: number): number {
return x;
}
function someInternalFunctionB(x: number): number {
return x;
}
// At the bottom, offer a public escape hatch for accessing certain functions
// you would like to be available for testing.
export const _private = {
someInternalFunctionA,
someInternalFunctionB,
};
在测试方面你可以这样做:
import { _private } from "./myModule";
test("someInternalFunctionA", () => {
expect(_private.someInternalFunctionA(42)).toEqual(42);
});
我喜欢这种方法的地方:
- 不需要直接用
export
标记someInternalFunctionA
- 很明显
_private
下的内容并不是 public 接口的正式部分。
我使用 Mocha/Chai 测试 JavaScript 前端代码,现在我们切换到 TypeScript。我有几个要测试的功能。但它们不应该是可导出的。我可以访问这个函数并在不添加 export
的情况下对其进行测试吗?
But they shouldn't be exportable. Can I get an access to this functions and test it without adding export to them?
一般来说,不会。可以访问私有 class 成员,但不能访问模块的未导出成员。
我会附和@Katana314 的评论——单元测试不应与非public 方法有关。尝试这样做表明您正在测试模块的实现细节,而不是模块声称要实现的合同。
正如您在相关问题中看到的,类 或模块内部测试私有函数的问题在 Whosebug 上引起了激烈的争论——以下可能是一种甚至没有讨论的架构解决方案:
如果这些功能足够重要,需要单独测试,但不应作为模块的一部分访问,是否应该将它们放在自己的模块中?
这将解决您的可访问性问题 - 它们现在是一个模块中的 public 函数,您可以轻松地从另一个模块中使用它们,而不是将它们作为该模块的一部分公开。
这完全是黑客攻击,但是嘿...
window.testing = {};
然后在你的模块中:
module.exports = {
myPublicFunction: myPublicFunction
};
window.testing.myModule = {
myPublicFunction: myPublicFunction,
myPrivateFunction: myPrivateFunction
};
无法访问未导出的模块函数。
module MyModule {
function privateFunction() {
alert("privateFunction");
}
}
MyModule.privateFunction(); // Generates a compiler error
但是,撇开私有方法测试的有效性问题不谈,您可以做的是。
将您的函数分组到实用程序 class 中,然后利用可以通过方括号表示法访问私有 class 成员这一事实。
module MyModule {
export class UtilityClass {
private privateFunction() {
alert("privateFunction");
}
}
}
var utility = new MyModule.UtilityClass();
//utility.privateFunction(); Generates a compiler error
utility["privateFunction"](); // Alerts "privateFunction"
我找到的最佳解决方案是以不同的名称导出私有函数,这样这个名称会提醒您不要在其他任何地方使用此函数。
export const getPrice__test = getPrice;
function getPrice(): number {
return 10 + Math.Random() * 50;
}
虽然无法直接访问未导出的函数,但仍有一种方法可以以“半隐藏”的方式导出它们。一种可能的方法是:
// In your library module declare internal functions as non-exported like normal.
function someInternalFunctionA(x: number): number {
return x;
}
function someInternalFunctionB(x: number): number {
return x;
}
// At the bottom, offer a public escape hatch for accessing certain functions
// you would like to be available for testing.
export const _private = {
someInternalFunctionA,
someInternalFunctionB,
};
在测试方面你可以这样做:
import { _private } from "./myModule";
test("someInternalFunctionA", () => {
expect(_private.someInternalFunctionA(42)).toEqual(42);
});
我喜欢这种方法的地方:
- 不需要直接用
export
标记someInternalFunctionA
- 很明显
_private
下的内容并不是 public 接口的正式部分。