我正在为我在公司的应用程序中编写的API的实现编写单元测试。这件事还是新手。在寻找关于如何对某些事情进行单元测试的答案时,我遇到了某种模式。它是这样的:
问题:
我有这个私有方法,我需要进行单元测试。
最高投票回答:
唐'吨
我也遇到了this article反对单位测试私有方法的争论。
基本上我是如何实现API的,我给出的是我先编写代码,然后将单元测试写入"以最坏的方式打破它" (正如我的上级所说)。一旦我发现有问题,我会在代码中修复它。对我而言,这似乎是OOD和TDD的混搭。这是一种合法的做法吗?
我首先得到这么多private
方法的原因是我需要将更大的代码块分解为方法。由于这些方法仅应在此API实现的范围内使用,因此我将它们设置为private
。由于我的团队建立的文件结构要求我将所有代码写入与API相对应的单个文件中,因此我无法将这些private
方法分成新类并将其设置为public
我的上司希望我也测试这些private
方法。但是,如果Assert
方法上的public
成功运行,我是否真的怀疑这是否真的有必要?
从我的观点来看,如果我对public
方法的测试返回我期望的值,我推断我的private
方法也可以像我预期的那样工作。
或者我错过了什么?
答案 0 :(得分:6)
核心要点是:存在单元测试以保证您的类在测试下的行为符合预期。
您的课程的行为通过可以从您课程的“外部”调用的方法表现出来。
因此,在尝试直接测试私有方法时,既没有需要也没有感觉。
当然,在运行单元测试时测量覆盖率 fair ;以了解代码中的哪些路径。此信息可用于增强测试用例(以获得更多覆盖);或删除生产代码(不是必需的)。
与您的问题保持一致:您不使用TDD来实现私有方法。
您使用TDD创建可以自动执行的特殊形式的“合同”。您验证需要完成的内容;不是如何它实际上是详细的。由于TDD方法包括连续重构,因此尤其如此。你编写测试,将它们变为绿色(通过编写生产代码);然后,在某些时候,您会考虑改进代码的质量。含义:您开始重新测试正在测试的类的内部方面。喜欢:创建更多私人方法,移动内容;甚至可能只创建内部辅助类等等。但是你继续运行你现有的测试......它们应该仍然有效;因为如上所述:你编写它们来检查外部可观察行为(尽可能)。
除此之外:你应该考虑“模糊”你的单元测试驱动到代码中的测试数据而不是担心私有方法。
我的意思是:不要试图手动查找使您的生产代码中断的测试数据,而是查看QuickCheck等尝试自动完成此操作的概念。
最后的话:如果你的管理层继续抨击“测试私人方法”;那么作为工程师,你有责任让他们相信他们错了。并且有很多材料可以支持它。
答案 1 :(得分:1)
此刻分割代码的方式是必需。您正在使用私有方法委派一些工作,因为,其他公共方法需要重复使用它,并且您不希望复制粘贴该代码。当然,由于这些方法无法用作独立方法,因此您将它们保密。
很好,至少你对 DRY (不要重复自己)的原则是正确的。
现在,另一种看待它的方法是,您希望将私有方法与其余代码分开,因为您希望拥有分离关注。如果你这样做,你会发现这些私有方法虽然不能单独使用,但实际上并不属于包含公共方法的类,因为它们没有解决同样的问题:这就是单一责任原则: SOLID 中的S.
您可以做的是将其移至另一个类(我称之为服务),而不是在您的类中使用私有方法,注入他们之前所在的类,并调用这些方法而不是调用私有方法。
你为什么要这样做?
这最后一点并不总是发生,但很多时候,确实如此。我发现在自我记录时重新使用现有数据服务更容易:正确命名的服务和正确命名的方法。 (你的同事会更容易发现它们)
现在,您不需要 来测试私有方法...因为它是公开的。
你可能认为这是作弊,因为你只是把它公之于众,但这来自一种非常合法的方法:分离关注点。
最终说明:
我确信你的上司要求你测试这段代码是正确的。他可以补充的一件事就是将这种分离分成不同的类别。此外,请确保使用依赖注入和反转控制容器注入这些类。不要使用new
语句对它们进行实例化,否则,您将无法断言使用正确的参数调用了正确的方法!