如何对未导出的函数进行单元测试?

新手上路,请多包涵

在 JavaScript ES6 模块中,可能有许多小的、易于测试的函数应该被测试,但不应该被导出。如何在不导出模块的情况下测试模块中的函数? (不使用 Rewire )。

原文由 Jordan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 855
2 个回答

导出一个“exportedForTesting”常量

function shouldntBeExportedFn(){
  // Does stuff that needs to be tested
  // but is not for use outside of this package
}

export function exportedFn(){
  // A function that should be called
  // from code outside of this package and
  // uses other functions in this package
}

export const exportedForTesting = {
  shouldntBeExportedFn
}

以下内容可用于生产代码:

 import { exportedFn } from './myPackage';

这可以用于单元测试:

 import { exportedFn, exportedForTesting } from './myPackage';
const { shouldntBeExportedFn } = exportedForTesting;

该策略为我团队中的其他开发人员保留了上下文线索 shouldntBeExportedFn() 除了测试外,不应在包外使用。

我多年来一直在使用它,我发现它工作得很好。

原文由 Jordan 发布,翻译遵循 CC BY-SA 4.0 许可协议

我希望我有一个更好的答案给你,乔丹。 😊 我过去在 JavaScript 和 C# 上下文中有非常相似的问题……

回答/不回答

在某些时候,我不得不接受这样一个事实,即如果我想要覆盖未导出/私有函数/方法的粒度单元测试,我真的应该公开它们。有人会说这是违反封装的,但也有人不同意。前一组人还会说,在导出/公开函数之前,它本质上是一个实现细节,因此不应该进行单元测试。

如果您正在练习 TDD ,那么 Mark Seeman 的解释应该是相关的(Pluralsight),并且希望它能阐明为什么可以公开内容。

我不知道您是否可以找到一些技巧来直接从您的单元测试中调用未导出的函数而不更改被测代码,但我个人不会那样做。

只是一个选择

另一种选择是将您的图书馆一分为二。比如说,库 A 是您的应用程序代码,而库 B 是包含您希望避免从 A 接口导出的所有函数的包。

如果它们是两个不同的库,您可以在非常精细的级别上控制公开的内容和测试方式。库 A 将仅依赖于 B 而不会泄露 B 的任何细节。 AB 然后可以独立测试。

当然,这将需要不同的代码组织,但它会起作用。 Lerna 等工具简化了 JavaScript 代码的多包存储库。

边注

老实说, 我不同意 AlexSzabó 的观点。通过测试使用它的函数来测试非导出函数并不是真正的单元测试。

原文由 Igor Soloydenko 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题