我遇到过很多情况,其中我的核心逻辑是在私有方法中。你将如何进行单元测试,有没有任何编译时操作来忽略未知/私有方法的编译错误?我知道对于代码的第二部分,我可以使用performSelector,但这是一个合理的解决方案吗?
例如:
[[self.objectMock expect] privateMethod];
or
[self.object callPrivateMethodsToExpectSomeOtherBehaviour]
编辑:
这里有一个例子来说明为什么我觉得我需要测试一些私有方法。这些测试不合理吗?否则,我该如何测试调用clear是否真的做到了它应该做的事情?
- (void)clear
{
self.orderNumber = nil;
[self.items removeAllObjects];
// Clear the rest of fields
}
- (void)testClearShouldRemoveOrderNumber
{
Order *order = [[Order alloc] init];
OCMockObject *orderPartialMock = [OCmockObject partialMockForObject:order];
[[orderPartialMock.items expect] setOrderNumber:nil];
[orderPartialMock clear];
[orderPartialMock verify];
}
- (void)testClearShouldRemoveItems
{
Order *order = [[Order alloc] init];
order.items = [[OCMockObject niceMockForClass:[NSMutableArray class]];
[[orderPartialMock.items expect] removeAllObjects];
[orderPartialMock performSelector@selector(clear)];
[orderPartialMock.items verify];
}
方法从来都不是"私有"的,因为一旦类实现了一个方法,它就可以发送给任何人。
所以,假设您有一个类Foo
,它有一个不在接口声明中的"私有"方法bar
。您仍然可以从任何地方调用bar
,尽管您可能会得到编译器诊断。
可能最简单的方法是在测试使用的类别中声明方法。例如:
@interface Foo (MyPrivateMethodsUsedForTesting)
- (void)bar;
@end
现在,您可以使用它们,编译器也不会抱怨。注意,这些方法不必在实际的MyPrivateMethodsUsedForTesting
类别中实现。这种技术有时也被称为"非正式协议"
编辑
此外,正如其他人所指出的,如果你需要访问私有方法,你可能应该重新审视你的设计。在做了大约30年之后,肯定会有一些时候,尤其是在测试中,你需要访问私人内容,但大多数时候这意味着某种类型的设计审查是有序的。
您不应该直接测试您的私有方法。相反,您需要通过公共方法对它们进行测试。这是programmers.stackexchange.com上讨论此事的一个问题的链接。
答案的总体思想是,您(或维护代码的任何其他人)应该可以随时通过更改签名、更改实现或完全删除它们来自由更改您的私有方法。班外的任何人都不应该在意——毕竟,这是最初将这些方法私有化的主要驱动因素。
如果您以不兼容的方式更改您的私有方法,那么您的公共方法的单元测试必须中断;否则,您没有很好地测试您的公共方法。实际上,这使得私有方法的单元测试变得不必要。
通常,您不需要对私有方法进行单元测试。
公开的方法告诉你你的类做什么——这是你关心的,你应该测试这些。私有方法关心你的类是如何完成它的工作的,你的测试不应该关心工作是如何完成的,只要它做得正确。
如果有一天你决定改变你的类的工作方式(即通过改变你的私有方法中的代码),而不改变你的类实际做了什么,那么你的单元测试应该会继续通过。通过尝试测试你的类内部,你创建了一个脆弱的测试,即使类仍然正常工作,它也可能会中断。
如果你发现仅仅使用公共方法很难彻底测试你的类,那么这是一个警告信号,表明你的类可能太大了——考虑把它分解成更小的部分。
您不需要对这些进行单元测试,事实上您不应该这样做
您将通过公共方法间接测试您的privat方法。私有方法是为公共方法完成任务的辅助方法。
既然你应该有足够的自由来更改你的私有方法,那么单元测试也会适得其反。
但是一定要测试公共方法的所有情况,这样所有私有方法都会被覆盖。