Objective C - 单元测试私有方法的核心功能?

ary*_*axt 9 unit-testing objective-c ios

我遇到过很多情况,我的核心逻辑是私有方法.您将如何进行单元测试,是否有任何类型的编译时操作来忽略未知/私有方法的编译错误?我知道对于代码的第二部分我可以使用performSelector,但这是一个合理的解决方案吗?

例如:

[[self.objectMock expect] privateMethod];
or 
[self.object callPrivateMethodsToExpectSomeOtherBehaviour]
Run Code Online (Sandbox Code Playgroud)

编辑:

这是一个示例,用于说明为什么我需要测试一些私有方法.这些测试不合理吗?我怎么测试调用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];
}
Run Code Online (Sandbox Code Playgroud)

Jod*_*ins 13

方法永远不会是"私有"的,因为一旦一个类实现了一个方法,它就可以发送给我的任何人.

所以,假设你有一个Foo带有"私有"方法的类bar,它不在接口声明中.您可以从任何地方仍然调用,bar但您可能会获得编译器诊断.

可能最简单的方法是在测试使用的类别中声明方法.例如:

@interface Foo (MyPrivateMethodsUsedForTesting)
- (void)bar;
@end
Run Code Online (Sandbox Code Playgroud)

现在,您可以在没有编译器抱怨的情况下使用它们.注意,这些方法不必在实际MyPrivateMethodsUsedForTesting类别中实现.这种技术有时也被称为"非正式协议".

编辑

另外,正如其他人所指出的那样,如果您需要访问私有方法,您可能应该重新访问您的设计.大约30年后这样做,肯定有时候,特别是测试,你需要访问私人的东西,但大多数情况下,它意味着某种类型的设计审查是有序的.


das*_*ght 9

您不应该直接测试您的私有方法.相反,您需要通过公共方法测试它们.这是关于programmers.stackexchange.com讨论此事的问题的链接.

答案的一般概念是,您(或维护您的代码的任何其他人)可以随时通过更改签名,更改实现或完全删除它们来更改您的私有方法.你班上没有人应该关心 - 毕竟,这是首先让这些方法变得私密的主要驱动力.

如果以不兼容的方式更改私有方法,则必须中断公共方法的单元测试; 否则,你没有做好测试你的公共方法的工作.实际上,这使得私有方法的单元测试变得不必要.


cod*_*box 5

通常,您不需要对私有方法进行单元测试.

公开的方法告诉你你的课程做了什么 - 这是你关心的,你应该测试这些.私有方法关注你的类如何完成它的工作,你的测试不应该关心如何完成工作,只要它正确完成.

如果有一天你决定改变你的类的工作方式(即通过改变私有方法中的代码),而不改变你的类实际做的事情,那么你的单元测试应该继续通过.通过尝试测试你的类的内部,你创建了一个脆弱的测试,即使该类仍然正常工作可能会破坏.

如果您发现很难通过公共方法彻底测试您的课程,那么这是一个警示标志,您的课程可能太大 - 考虑将其分解成更小的部分.