2014-02-28 47 views
0

我有使用OCMock测试用例,其执行以下操作:OCMock:嘲笑协议不正确停止

CAAOAuth2AuthenticationManager *oAuth2AuthManager = [[CAAOAuth2AuthenticationManager alloc] init]; 
id authDelegate = [OCMockObject mockForProtocol:@protocol(CAAAuthenticationDelegate)]; 
id partialAuthManagerMock = [OCMockObject partialMockForObject:oAuth2AuthManager]; 
id resultMock = [OCMockObject mockForClass:[CAAOAuth2AuthenticationResult class]]; 
[[authDelegate reject] didFailWithError:OCMOCK_ANY]; 

[[[partialAuthManagerMock expect] andForwardToRealObject] authenticateWithResult:OCMOCK_ANY formData:OCMOCK_ANY delegate:authDelegate]; 
[[partialAuthManagerMock reject] authenticateWithOptions:OCMOCK_ANY delegate:authDelegate]; 

[[[resultMock expect] andReturnValue:OCMOCK_VALUE(YES) ] isAuthenticated]; 
[[resultMock reject] refreshToken]; 

当运行测试的情况下,第二测试情况下(完全不同的测试类和文件)后者也使用CAAAuthenticationDelegate协议失败,SIGABRT:

2014-02-28 10:11:24.594 otest[37161:303] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[CAAAuthenticationDelegate]: unexpected method invoked: didReceiveAuthenticationWithResult:OCMockObject[CAAOAuth2AuthenticationResult] 
stubbed: didFailWithError:<OCMAnyConstraint: 0xa913fc0>' 

但是,我没有在第二次测试的情况下使用任何嘲弄。我试图清除与stopMocking模拟没有成功。

下模拟设置工作没有任何问题:

[[authDelegate reject] didFailWithError:OCMOCK_ANY]; 

[[[partialAuthManagerMock expect] andForwardToRealObject] authenticateWithResult:OCMOCK_ANY formData:OCMOCK_ANY delegate:authDelegate]; 
[[partialAuthManagerMock expect] authenticateWithOptions:OCMOCK_ANY delegate:authDelegate]; 

[[[resultMock expect] andReturnValue:OCMOCK_VALUE(NO) ] isAuthenticated]; 
[[[resultMock expect] andReturn:refreshToken] refreshToken]; 

谁能告诉我,为什么出现这种情况?

+1

什么是引发异常时的完整堆栈跟踪?你在某处留下了一个模拟悬念。它可能是你的和ForwardToRealObject,这是否做任何类型的异步活动,可以在测试完成后挂在内存中? – ImHuntingWabbits

回答

0

作为一种解决方法,您可以创建一个协议的空实现,然后模拟一个真实的对象吗?我用这种方法运气更好 - 嘲笑协议只会导致我不知所措。

@interface TestAuthDelegateImpl : NSObject <CAAAuthenticationDelegate> 
@end 
@implementation 
- (void)didFailWithError:(id)whatever; 
@end 

就是这样的。然后只是mockForClass它 - 可能会更好的表现。

0

这似乎意味着您的CAAOAuth2AuthenticationManager实例仍然在后面的测试中,并且仍然设置了旧的模拟委托,并且调用了一些方法,导致该委托方法被调用。 CAAOAuth2AuthenticationManager是单例类型对象,还是与第二次测试中使用的实例相同?完成后,我会在第一次测试中将委派重置为无验证管理器。

你也可以使用niceMockForProtocol,它会默默地忽略任何没有明确拒绝设置的方法调用。除了例外情况,它听起来像拒绝已被删除,并且委托模拟现在只会在发送给它的任何方法上引发异常,因为也没有设置期望。

此外,我会使用STAssertNoThrow()实际调用您的真实代码(这可能发生在上面显示的设置后)。拒绝和意外的方法将引发异常,这可能会导致模拟对象无法正确解除分配并为后续测试创建问题。如果通过测试通过,这可能不是一个问题。

要检查的最后一件事是如果您的委托属性被声明为“分配”而不是“弱”。如果它是“分配”,并且你不清零它并且它被释放,那么任何事情都可能发生(segfault,或者一个全新的对象被分配到同一个内存地址)。尽管如此,这似乎也不太可能。