我正在尝试对一个对象做一个简单的模拟,
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/