为什么我的对象的弱委托属性在我的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对象的方式。