为什么我的对象的弱委托属性在我的unit testing中为零?

我为这个unit testing有一个非常简单的设置。 我有一个具有委托属性的类:

@interface MyClass : NSObject ... @property (nonatomic, weak) id<MyDelegateProtocol> connectionDelegate; ... @end 

我在testing中设置了委托:

 - (void)testMyMethod_WithDelegate { id delegate = mockDelegateHelper(); // uses OCMock to create a mock object [[delegate expect] someMethod]; myClassIvar.connectionDelegate = delegate; [myClass someOtherMethod]; STAssertNoThrow([delegate verify], @"should have called someMethod on delegate."); } 

但是这个委托实际上并没有设置在我的unit testing的第3行,所以#someMethod永远不会被调用。 当我改变它

 myClassIvar.connectionDelegate = delegate; STAssertNotNil(myClassIvar.connectionDelegate, @"delegate should not be nil"); 

它在那里失败。 我正在使用ARC,所以我的直觉是,弱财产被释放。 果然,将其改为strong使STAssertNotNil通过。 但是我不想和一个代表这样做,我不明白为什么这里有所作为。 从我读过的,ARC中的所有本地引用都很strong ,并且STAssertNotNil(delegate)通过。 为什么我的弱委托属性为零当局部variables中的同一个对象不是?

这是iOS运行时的错误。 以下讨论更详细。 简而言之,iOS ARC运行时似乎无法处理对代理的弱引用。 OSX运行时可以。

http://www.mulle-kybernetik.com/forum/viewtopic.php?f=4&t=252

据我所知,这个讨论已经提交给苹果公司。 如果有人有一个明智的解决办法…

我真的不知道这里发生了什么,但是OCMock从mockForProtocol:方法返回一个自动发布的mockForProtocol: ,我认为这是正确的。 也许ARC有NSProxies的问题? 无论如何,我通过声明variables__weak解决这个问题:

 - (void)testMyMethod_WithDelegate { // maybe you'll also need this modifier inside the helper __weak id delegate = mockDelegateHelper(); ... 

在这种情况下,它实际上不需要是__strong (默认值),因为它是自动发布的,并且不会保留它。

解决方法是使用部分模拟。

 @interface TestMyDelegateProtocolDelegate : NSObject <MyDelegateProtocol> @end @implementation TestMyDelegateProtocolDelegate - (void)someMethod {} @end @implementation SomeTest { - (void)testMyMethod_WithDelegate { id<MyDelegateProtocol> delegate = [[TestMyDelegateProtocolDelegate] alloc] init]; id delegateMock = [OCMockObject partialMockForObject:delegate] [[[delegateMock expect] someMethod] myClassIvar.connectionDelegate = delegate; [myClass someOtherMethod]; STAssertNoThrow([delegate verify], @"should have called someMethod on delegate."); } @end 

我不是ARC专家,但我的猜测是mockDelegateHelper()正在返回一个弱对象。 结果delegate在第二行代码执行之前是零。 我想冒险猜测,无论是mockDelegateHelper()是罪魁祸首或OCMock是如何操纵和创build对象的方式。