63

我正在一个玩具项目中尝试测试驱动开发。我可以让测试为我的类的公共接口工作(尽管我仍然在围栏上,因为我编写的测试代码比正在测试的方法中的要多)。

我倾向于使用很多私有方法,因为我喜欢保持公共接口干净;但是,我仍然想对这些方法进行测试。

由于 Cocoa 是一种动态语言,我仍然可以调用这些私有方法,但是我在测试中收到警告说我的类可能不会响应这些方法(尽管它显然会响应)。因为我喜欢在没有警告的情况下编译,所以我的问题是:

  1. 如何在 Xcode 中关闭这些警告?
  2. 我还能做些什么来关闭这些警告吗?
  3. 我在尝试“白盒”测试时做错了吗?
4

7 回答 7

125

请记住,在 Objective-C 中实际上没有“私有方法”之类的东西,这不仅仅是因为它是一种动态语言。按照设计,Objective-C 对 ivars 有可见性修饰符,但对方法没有——你可以调用任何你喜欢的方法并非偶然。

@Peter的建议很棒。为了补充他的答案,我使用的另一种方法(当我不想/只需要私有方法的标头时)是在单元测试文件本身中声明一个类别。(我使用@interface MyClass (Test)它作为名称。)这是在发布代码中添加不必要的膨胀方法的好方法,例如用于访问被测类可以访问的 ivars。(当使用属性时,这显然不是问题。)

我发现这种方法可以很容易地公开和验证内部状态,以及添加仅测试方法。例如,在这个单元测试文件中,我编写了一个-isValid验证二进制堆正确性的方法。在生产中,这种方法会浪费空间,因为我假设堆是有效的——如果我修改代码,我只在测试单元测试回归时才关心它。

于 2009-07-08T16:50:08.423 回答
89

如何在 Xcode 中关闭这些警告?

不。

我还能做些什么来关闭这些警告吗?

不。

我在尝试“白盒”测试时做错了吗?

不。

解决方案是将您的私有方法移动到其自己的标题中的类别。将此标头导入到真实类和测试用例类实现文件中。

于 2009-07-08T14:56:49.117 回答
4

看起来另一个问题有答案:有没有办法在 Xcode 中抑制警告?

于 2009-07-08T14:53:31.120 回答
4

几天前我开始使用 TDD 时,我正在处理同样的问题。我在Test-Driven iOS Development一书中发现了这个非常有趣的观点:

我经常被问到,“我应该测试我的私有方法吗?” 或相关问题“我应该如何测试我的私有方法?” 问第二个问题的人假设第一个问题的答案是“是”,现在正在寻找一种方法在他们的测试套件中公开他们的类的私有接口。

我的回答依赖于对一个微妙事实的观察:您已经测试了您的私有方法。通过遵循测试驱动开发中常见的红绿重构方法,您设计了对象的公共 API 来完成这些对象需要完成的工作。通过测试指定的工作——以及测试的持续执行确保你没有破坏任何东西——你可以自由地组织你认为合适的类的内部管道。

您的私有方法已经过测试,因为您所做的只是重构您已经测试过的行为。您永远不应该陷入私有方法未经测试或未完全测试的情况,因为您只有在看到有机会清理公共方法的实现时才创建它们。这确保了私有方法的存在只是为了支持在测试期间必须调用它们的类,因为它们肯定是从公共方法调用的。

于 2014-02-05T10:15:07.227 回答
3

虽然拥有私有标头或定义自己的类别可能是更正确的解决方案,但还有另一个非常简单的解决方案:在调用方法之前将对象强制转换为 (id)。

于 2009-07-12T20:17:50.877 回答
3

如果您不想将私有方法实现分布在多个源文件中,对 Category 解决方案的改进是在由现有类导入的头文件中定义 Extension(本质上是匿名 Category - 请参阅Apple 的文档) ' 实现和相关的单元测试源文件。

如果私有方法的实现不存在于主 @implementation 块中,使用扩展允许编译器向您发出警告。这个链接很好地说明了这一点。

于 2012-04-25T00:50:31.540 回答
1

轻松的工作。步骤: 1. 你有 -(NSString*)getTestString; 在接口 Foo 的目标 m 文件中

  1. 在单元测试文件中添加一个类别:

    @interface DemoHomeViewController() -(NSString*)getTestString; @结尾

然后,现在就做任何你想做的事。

于 2016-10-11T07:42:56.897 回答