ios - OCMock [OCMAnyConstraint isProxy] : message sent to deallocated instance, 发生了什么事?

标签 ios unit-testing reactive-cocoa ocmock

我正在尝试对一个对象做一个简单的模拟,

HTAppleWatchDevice * shared = [[HTAppleWatchDevice alloc] init];
id watchMock = [OCMockObject partialMockForObject:shared];
[deviceManager setAppleWatchDevice:watchMock];

void (^replyDict)(NSDictionary*) = ^void(NSDictionary* response){};

[[watchMock expect] dataReturnedFromServer:[OCMArg isNotNil] ofType:[OCMArg any]];
[watchMock handleWatchKitExtensionRequest:request reply:replyDict];
[watchMock verifyWithDelay:10];

确实调用了预期的方法,但我得到了此类错误,具体取决于第二个 OCMArg:

[OCMAnyConstraint isProxy]: message sent to deallocated instance 0x7f954608b630

我确实尝试过将预期的调用放在 handleWatchKitExtensionRequest:reply: 中,使用虚拟数据,但出现了完全相同的错误。

[self dataReturnedFromServer:@[] ofType:[self supportedMIMETypes].firstObject];

更新:该类使用 react 性 cocoa ,它交换对象的类,我怀疑由于重叠的类交换可能会发生交互。我要标记它,直到我数完为止。

举个例子,我注释掉验证行

[[watchMock expect] dataReturnedFromServer:[OCMArg isNotNil] ofType:[OCMArg any]];
[watchMock handleWatchKitExtensionRequest:request reply:replyDict];
//[watchMock verifyWithDelay:10];

但是另一个异常出现了,一旦之前的 watchMock 被释放:

RACKVOTrampoline.m:dispose method, exception, upon next test start…:

[target removeObserver:RACKVOProxy.sharedProxy forKeyPath:self.keyPath context:(__bridge void *)self];

error: -[HTAppleWatchDeviceTest nameOfNextTest] : failed: caught "NSRangeException", "Cannot remove an observer for the key path "delegate" from because it is not registered as an observer."

有什么想法吗?

最佳答案

好吧,让我展示一下我通过 Method Swizzling 想出的解决方法——尽管我不会接受它。

HTAppleWatchDeviceTest.m

static XCTestExpectation* roundTripExpectation = nil; //static var is avail from this FILE

-(void) testPerceiveActuateRoundTrip{
roundTripExpectation = [self expectationWithDescription:@"should return data"];
HTAppleWatchDevice * shared = [deviceManager appleWatchDevice];

static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
    //steps
    //1 identify old and new selectors
    SEL oldSelector = @selector(dataReturnedFromServer:ofType:);
    SEL newSelector = @selector(HTTest_dataReturnedFromServer:ofType:);
    //2 get old method for old selector
    Method oldMethod = class_getInstanceMethod([shared class], oldSelector);
    //3 get new implementation for new selector
    Method newMethod = class_getInstanceMethod([self class], newSelector);
    //4 set new implementation for old selector -- might fail
    BOOL addedFine = class_addMethod([shared class], oldSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
    //5 set old implementation for new selector, used to continue normal execution
    class_addMethod([shared class], newSelector, method_getImplementation(oldMethod), method_getTypeEncoding(oldMethod));
    //6 swap new and old implementations for HTAppleWatchDevice, if not already set above
    //NOTE: will NOT effect step 5, as implementation was set directly. WILL effect [self HTTest_dataReturnedFromServer:ofType:] -> oldImplementation (on HTAppleWatchDevice), but NBD
    if (!addedFine){
        method_exchangeImplementations(oldMethod, newMethod);
    }
});

void (^replyDict)(NSDictionary*) = ^void(NSDictionary* response){};
[shared handleWatchKitExtensionRequest:request reply:replyDict];
[self waitForExpectationsWithTimeout:10 handler:nil];
roundTripExpectation = nil;
}

//this method will ONLY be called with [self class] == HTAppleWatchDevice
-(void)HTTest_dataReturnedFromServer:(NSArray*)activations ofType:(NSString*)type{
[self HTTest_dataReturnedFromServer:activations ofType:type];
[testPerceiveActuateRoundTripExpectation fulfill];
}

关于ios - OCMock [OCMAnyConstraint isProxy] : message sent to deallocated instance, 发生了什么事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29784390/

相关文章:

ios - 无法从 linkedIn 获取 'bio' 、 'industry' 、 'professional headline' 和 'number of connections' 信息

ios - @strongify 的原因是什么

objective-c - 这两个实例是同一个类吗? (ReactiveCocoa 文档示例)

ios - 使用没有文件扩展名的 SDWebImage 加载图像

ios - iPhone X - Safe Area 没有实现全面屏体验?

java - 在 Spring 中用单元测试覆盖 websocket Controller 的最简单方法是什么?

java - 在单元测试中禁用 JMS 使用 bean

unit-testing - 使用 Mockoon 和 Nunit 模拟 API 调用进行单元测试

ios - ReactiveCocoa 如何监听数据模型属性的变化

ios - iPhone UI 小部件大小调整