Dov*_*Dov 4 cocoa unit-testing objective-c key-value-observing ocmock
我想测试Key-Value-Observation是否适用于我的一类.它有一个属性,这取决于另一个属性.它们的设置如下:
+ (NSSet *)keyPathsForValuesAffectingSecondProperty {
return [NSSet setWithObjects:
@"firstProperty",
nil];
}
- (NSArray *)secondProperty {
return [self.firstProperty array];
}
Run Code Online (Sandbox Code Playgroud)
我想运行一个单元测试来验证firstProperty
更改时,绑定的对象是否secondProperty
获得通知.起初我以为我可以使用+[OCMockObject observerMock]
,但它看起来只能用于NSNotificationCenter
.测试这个的最佳方法是什么?
@ chrispix的答案激励我在不同的方向工作后,我在这方面工作了一段时间.我从这开始:
id objectToObserve = [[TheClassBeingTested alloc] init];
id secondPropertyObserver = [OCMockObject mockForClass:[NSObject class]];
[[secondPropertyObserver expect] observeValueForKeyPath:@"secondProperty"
ofObject:objectToObserve
change:OCMOCK_ANY
context:[OCMArg anyPointer]];
[objectToObserve addObserver:secondPropertyObserver
forKeyPath:@"secondProperty"
options:NSKeyValueObservingOptionNew
context:NULL];
// Do something to modify objectToObserve's firstProperty
[secondPropertyObserver verify];
Run Code Online (Sandbox Code Playgroud)
当我运行此测试代码时,我收到以下消息:
OCMockObject[NSObject]: unexpected method invoked: isKindOfClass:<??>
expected: observeValueForKeyPath:@"firstProperty" ofObject:
Run Code Online (Sandbox Code Playgroud)
我做了一些调查,发现-isKindOfClass:
模拟对象没有想到的调用是传递给一个NSKeyValueObservance
类对象.
我尝试添加以下代码来模拟响应,但是YES
并且NO
两者的值都失败EXC_BAD_ACCESS
,并且堆栈中存在NSKeyValueWillChange的异常.
BOOL returnVal = NO;
[[[secondPropertyObserver stub] andReturnValue:OCMOCK_VALUE(returnVal)] isKindOfClass:[OCMArg any]];
Run Code Online (Sandbox Code Playgroud)
我更谨慎地走了一步,发现我的代码没有导致这个异常 - 它autoreleasepool
正在被排空.然后我突然意识到我需要移除观察者.以下是完整的解决方案,包括删除观察者.
id objectToObserve = [[TheClassBeingTested alloc] init];
id secondPropertyObserver = [OCMockObject mockForClass:[NSObject class]];
BOOL returnVal = NO;
[[[secondPropertyObserver stub] andReturnValue:OCMOCK_VALUE(returnVal)] isKindOfClass:[OCMArg any]];
[[secondPropertyObserver expect] observeValueForKeyPath:@"secondProperty"
ofObject:objectToObserve
change:OCMOCK_ANY
context:[OCMArg anyPointer]];
[objectToObserve addObserver:secondPropertyObserver
forKeyPath:@"secondProperty"
options:NSKeyValueObservingOptionNew
context:NULL];
// Do something to modify objectToObserve's firstProperty
[secondPropertyObserver verify];
[objectToObserve removeObserver:secondPropertyObserver
forKeyPath:@"secondProperty"];
Run Code Online (Sandbox Code Playgroud)