gpt4 book ai didi

unit-testing - 什么时候在单元测试中绕过封装合适?

转载 作者:行者123 更新时间:2023-11-28 19:46:07 25 4
gpt4 key购买 nike

我最近才知道 powermock's Whitebox功能。 (总而言之,它允许您直接测试私有(private)方法或直接从单元测试中修改私有(private)成员——同时保持它们私有(private)!)

我知道有一些想法不赞成对可见方法以外的任何内容进行单元测试,但是该死,有时您只需要一个简单的测试来确保深层辅助方法正在做它应该做的事情......没有经历可能会产生巨大开销的准备父方法所需的参数和模拟以过滤到您的方法..然后您必须做一些魔术来提取该内部方法的结果。简而言之,有时测试这些内部方法需要最复杂和最难遵循的单元测试。 (而且,仅供引用,我们公司有 100% 单元测试覆盖率的政策。这些方法必须经过测试!)

我知道 one methodology是更改方法访问器以允许单元测试(例如,从 private 更改为 protected ,但 powermock Whitebox 允许直接测试而不更改源代码。

尽管如此,妈妈总是说,“仅仅因为你可以,并不意味着你应该。”

像这样测试内部方法是否合适?如果是这样,我应该使用什么经验法则?

最佳答案

让我们首先承认 this is a partially religious debate .

我的观点是测试 private方法是你应该经常避免的东西,但也有异常(exception)。

为什么我不应该测试 private方法?

因为您正在测试您的应用程序是否工作,而不一定是它是如何工作的。一个 private方法不是您的程序公开的 API 的一部分,它本质上是一个实现细节。

反对通过封装来解决对您设置的限制并仍在测试它的一个常见论点是,它可能会破坏测试特定实现的测试。

在“正常”测试中,我们测试 public方法,因为它们构成了我们的程序:如果我们知道所有公共(public) API 都可以工作,那么我们就知道程序可以工作。如果您的应用程序结构良好,您将有多个 API 层,这些层不断将测试细化为更小的单元,以便您清楚地了解哪些地方可能会出错。

关于private实现的事情方法是它们总是会在某个时刻被 public 调用。方法,这将得到测试。一个 private方法是被测单元的实现细节,因此不应单独测试。

此辅助方法不受 API 约束,因此无法保证其效果会保持不变;在不调整整体功能的情况下更改实现细节现在将破坏您对该方法的测试。因此,即使您的程序仍然运行良好,但您现在的测试已损坏。这些测试是不稳定的:不改变您的功能的重构仍然可能导致您必须删除单元测试,因为它们不再相关(这本身很危险,因为您必须非常确定测试实际上是多余的)。

我为什么要测试 private方法?

只有少数事情是非黑即白的,这不是其中之一。我认为新代码不应该测试 private方法,但这就是我区分的地方:新代码。

如果您继承了遗留代码库,那么架构很可能不是很漂亮。您可能不得不跳过箍,整体代码流可能会更好。

因此,您要做的第一件事就是编写一些单元测试,保证在您破坏功能时告诉您。到目前为止一切顺利,我们现在可以进入实际的重构过程。让我们从这 500 行开始 private方法?

记住前面的评论,您现在必须查看代码流并查看 public方法使用该 private方法并在进行更改时密切关注它们。

为了便于使用,我将在这里编写测试,只测试 private 的合约。方法对应用程序的其余部分:只要您的方法结果没有不同,您就知道它不会影响任何其他遗留方法。有了这些知识,您现在可以轻松地重构该方法中的所有内容。当某些东西确实破裂时;您可以立即使用您的辅助方法,而不必通过公共(public) API 方法。

请记住,我只会对大型重构操作执行此操作:这些首先是临时测试,而“实现细节”实际上是 500 行代码:这是一个包含很多细节的细节。

我应该如何测试 private方法?

关于如何使这些可测试,您在此处有几个选项:

反射

我相信这就是 WhiteBox 使用的。尽管如此,它引起了一些人的注意:没有静态类型(更改方法名意味着破坏测试),it's expensive使用反射的代码往往更难阅读。

私有(private)对象

我没有看过确切的实现,但我很确定这在幕后使用了反射。基本上它通过一个方便的界面提供反射方法。我还没有看到它使用太多(部分是因为我将使用反射作为绝对的最后手段)但它就在那里。

MSDN

萃取

这将是我的第一种方法:这个辅助方法是否重要到足以使其独立?您可能会对此说"is",因为显然它已经足够重要,您需要对其进行明确的测试。

民众

最明显的选择:简单地做 public .这遵循与 Extraction 相同的想法:“它可以独立吗?”。这里的区别在于您仍然将其视为当前类的一部分,您只是提升了它的访问权限,而将其提取到不同的类也表明您所讨论的不仅仅是一个辅助方法。

内部的

此选项采用中间路线:如果我将其设为内部(C# 上下文)并使用 [InternalsVisibleTo]属性,你可以让它internal同时为您的测试程序集提供测试它的可能性(并且仍然使其远离公共(public) API)。

这带来了人们只将其视为实现细节并在破坏测试(考虑特定实现)的同时更改实现的风险。

此外,这也会增加您的应用程序和测试之间的耦合。

都认为这取决于您自己的喜好:有多种测试选项 private方法,双方都有一些论据。就我个人而言,我会远离测试此类实现细节的麻烦,而是看看我可以做些什么来改进我的架构。问题很可能会以这种方式自行解决。

关于unit-testing - 什么时候在单元测试中绕过封装合适?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23702784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com