【问题标题】:Can internal code be tested without having to mark the test code as internal?是否可以在不必将测试代码标记为内部的情况下测试内部代码?
【发布时间】:2018-03-15 14:09:33
【问题描述】:

我有一个 F# 库,其中包含许多我想测试的非公开内容。目前,所有不属于程序集公共 API 的代码都标记为 internal(具体来说,它位于标记为 internal 的模块中)。我使用InternalsVisibleToAttribute 使此代码对我的测试程序集可见。但是,为了编译测试程序集,所有在其签名中使用内部类型的测试(其中大多数,因为我使用 FsCheck 自动生成测试输入)也必须标记为内部(这需要应用于每个函数,因为 xunit 不会发现内部模块)。此外,任何专门用于 FsCheck 生成的类型(例如 type ValidCustomer = ValidCustomer of Customer 其中Customer 是我的内部域类型)也需要标记为内部,并且 FsCheck 在创建内部类型时似乎卡住了,因此测试不会运行。

是否有任何方法可以测试内部 F# 代码(来自单独的测试程序集),而不必将签名依赖于内部类型的所有测试标记为内部?现在我只是倾向于在原始代码中根本不做任何内部操作,但理想情况下,有一种方法可以让我的干净 API 蛋糕也吃掉。

【问题讨论】:

  • 为什么你的 domain 类型是内部的?除非您使用的术语与DDD 大不相同,否则域模型是您的应用程序中最重要的部分。这就是应用程序首先存在的原因......
  • @MarkSeemann 也许 domain types 是错误的术语。在这种特殊情况下,它是一个从数据仓库数据库读取数据、聚合销售数据等数据并将该数据公开给 Web API 的单个项目。 API 获取的主要是数字数据,但是有很多内部的,嗯,域类型(客户、订单等 - 他们正在对域进行建模,即使它们没有在这个项目之外使用)用于生成汇总数据。
  • 好的,但是将这些类型设为内部的动机是什么?
  • 动机是清理程序集的公共 API,以避免对导入它的其他项目应该使用什么造成混淆。在我的特殊情况下并不那么重要——它是一家小公司的一个小项目——但代码的某些部分仅用于汇编内部使用,我可以想象假设的(但现实的)示例,它不是自动的从项目 B 中明确引用项目 B 的项目 A 应该(而不应该)使用什么。
  • IME,总是有更好的方法来解决这些问题。在 OOD 中,它们属于术语封装,但您可以在 FP 中进行类似操作。不过,我无法在不知道细节的情况下告诉你明确的替代方案......

标签: f# xunit fscheck


【解决方案1】:

我发现 OO 世界通常会非常反对尝试直接测试任何内部/私有的东西。

在函数世界中,我看到了更多的趋势,即只公开不供公众使用的公共函数,以便对其进行测试。看到这个comment from Edward Kmett

当我开始编写 Haskell 时,我开始重新思考我过去处理封装和隐藏的方式。

...

一般来说,我非常喜欢通过某种 .Internal 模块为我的数据类型公开所有重要细节、构造函数和所有内容,即使我希望 API 的其余部分具有封装性和安全性。

...

作为一个副作用,您可以使用这些新暴露的胆量进行良好的测试。 =)

原始评论中有更多细节,并且有一次谈话,他详细讨论了这一点,但我现在找不到。

你也可以给模块起一个非常难看的名字,比如 __INTERNAL__ 来阻止它的使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多