在Objective-C中如何对私有方法进行单元测试?

43

我使用GHUnit进行单元测试。我想要测试私有方法但不知道该如何测试。我发现了很多关于为什么要或者不要测试私有方法的答案,但是没有找到如何测试它们的答案。

本文不会讨论是否应该测试私有方法,而是专注于如何测试它们。

请问是否有人能给我一个测试私有方法的示例?


你面临的问题是什么?就像测试普通方法一样。 - Abizern
测试私有方法的决定是问题空间的一部分,而不是解决方案空间的一部分。 - Sergey Kalinichenko
@Abizern 这意味着 myClass 没有声明选择器 'myMethod' 的可见 @interface。 - Geek
@dasblinkenlight 它说“没有已知的选择器'myMethod'的实例方法”。 - Geek
4个回答

118

Objective-C中的方法并不是真正的私有。您收到的错误消息是编译器无法验证您调用的方法是否存在,因为它没有在公共接口中声明。

解决方法是在类别中公开私有方法,这告诉编译器该方法是存在的。

因此,请将以下内容添加到测试用例文件的顶部:

@interface SUTClass (Testing)

- (void)somePrivateMethodInYourClass;

@end

SUTClass是您编写测试的类的实际名称。

这将使您的私有方法可见,您可以在没有编译器警告的情况下进行测试。


但是这样做会暴露这些方法。 - Geek
6
如果您在测试类中这样做,那么您只能暴露给测试方法。 - Abizern
但是你说我必须在我正在测试的类中编写这个,而不是在测试类中。 - Geek
1
不是的。我说把类别添加到包含测试用例的文件顶部。我在哪里说要在主类中编写它? - Abizern
太好了!之前我一直有一个大问题,就是仅仅为了单元测试而暴露私有属性/方法。现在至少有一种更少侵入的方式可以暴露它们。谢谢!! - Hampden123
显示剩余3条评论

7

有点晚,但我刚刚开始接触TDD。

私有方法不应该被测试。因为你编写私有方法来支持公共方法,因此测试公共方法间接地测试了支持它们的私有方法。

原则“不应该测试私有方法”得到了原则“当你需要测试私有方法时,可能意味着你应该将这些方法移到单独的类中”的支持,从而使它们成为公共方法。


13
如果你先写了一段代码而不是先写单元测试,那么这就不是TDD(测试驱动开发)。但是,假设你的公共方法使用了几个私有方法,那么当它失败时,你如何知道哪一个失败了? - Cristi Băluță

4

如果一个方法是私有的,你就不应该测试它。

想一想这个问题。你应该测试方法的行为和契约,而不是内部实现。


1
那么,如果我们有一个需要测试的内部实现,这是否表明设计上存在缺陷,即该方法实际上应该在另一个类中编写为公共方法,并在初始类中私下隐藏? - Mazyod
2
如果没有的话,那么(表面上看)在单个类中使用私有方法创建整个应用程序不应该被测试。 - Mazyod
完美的Mazyod,我完全同意你的补充信息。 - seufagner
我其实不同意Mazyod的观点。要了解为什么,请阅读我的回答。 - Lord Zsolt

4

同意 @Lord Zsolt 的观点

还请注意下面的内容(来自 Test-Driven iOS Development ISBN-10: 0-321-77418-3,ISBN-13: 978-0-321-77418-7)

测试私有方法
我经常被问到,“我应该测试我的私有方法吗?”或相关问题“我应该如何测试我的私有方法?”问第二个问题的人已经假定了对第一个问题的答案是“是”,现在正在寻找一种方法来在测试套件中公开其类的私有接口。
我的答案依赖于观察微妙的事实:您已经测试过您的私有方法。通过遵循测试驱动开发中常见的红绿重构方法,您设计了对象的公共API来完成这些对象需要完成的工作。通过测试指定的工作 - 并且测试的持续执行确保您没有破坏任何东西 - 您可以自由地组织类的内部管道。您的私有方法已经得到测试,因为您所做的一切都是重构行为,而您已经对此进行了测试。
您永远不应该陷入未经测试或未完全测试的私有方法的情况,因为只有在看到清理公共方法的机会时才会创建它们。这确保了私有方法仅存在于支持类的公共行为,并且必须在测试期间调用它们,因为它们肯定会从公共方法中调用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接