我打這個限制也是如此。基本思想是覆蓋respondsToSelector
:(不能被OCMock可靠地嘲笑)。
我做了以下這樣的課,爲你做到這一點。 然後,您可以使用它,如下所示:
延長GCOCMockOptionalMethodSupportingObject
,並實現你的協議
@interface GCTestDelegate : GCOCMockOptionalMethodSupportingObject <GCDelegate>
@end
@implementation GCTestDelegate
//required methods
- (void)requiredMethod{
}
@end
// create your testdelegate
self.classBeingTested.delegate = [OCMock partialMockForObject:[GCTestDelegate new]];
[self.classBeingTested.delegate markSelectorAsImplemented:@selector(optionalMethod:)];
[[self.classBeingTested.delegate expect] optionalMethod:self.classBeingTested];
[self.classBeingTested doSomethingThatwillCheckIfYourDelegateRespondsToYourOptionalMethod];
如果你不叫markSelectorAsImplemented
,那麼你的classBeingTested
將獲得NO的respondsToSleectorForThatMethod
我已經把這裏的代碼。我使用這個效果很好。感謝#iphonedev上的jer讓我在這條路上脫穎而出(重寫respondsToSelector
是他的想法,我正在做一些瘋狂的運行時方法增加 - 這是更清潔的methinks)。
這裏的代碼
/**
* This class is specifically useful and intended for testing code paths that branch
* pending implementation of optional methods.
* OCMock does not support mocking of protocols with unimplemented optional methods.
* Further compounding the issue is the fact that OCMock does not allow mocking of
* respondsToSelector (in fact, it does but the behaviour is undefined),
* As such this class can be extending to implement a given protocol, the methods can be mocked/expected
* as normal, but in addition we can tell the class to report it conforms to a protocol method or not.
*
*/
@interface GCOCMockOptionalMethodSupportingObject : NSObject
- (void)markSelectorAsImplemented:(SEL)aSelector;
- (void)unmarkSelectorAsImplemented:(SEL)aSelector;
@end
#import "GCOCMockOptionalMethodSupportingObject.h"
@interface GCOCMockOptionalMethodSupportingObject()
@property(nonatomic, strong) NSMutableArray *implementedSelectors;
@end
@implementation GCOCMockOptionalMethodSupportingObject {
}
//////////////////////////////////////////////////////////////
#pragma mark init
//////////////////////////////////////////////////////////////
- (id)init {
self = [super init];
if (self) {
self.implementedSelectors = [NSMutableArray array];
}
return self;
}
//////////////////////////////////////////////////////////////
#pragma mark public api
//////////////////////////////////////////////////////////////
- (void)markSelectorAsImplemented:(SEL)aSelector {
if (![self isImplemented:aSelector]) {
[self.implementedSelectors addObject:NSStringFromSelector(aSelector)];
}
}
- (void)unmarkSelectorAsImplemented:(SEL)aSelector {
for (NSString *selectorValue in [self.implementedSelectors mutableCopy]) {
SEL storedSelector = NSSelectorFromString(selectorValue);
if (sel_isEqual(aSelector, storedSelector)) {
[self.implementedSelectors removeObject:selectorValue];
break;
}
}
}
//////////////////////////////////////////////////////////////
#pragma mark private impl
//////////////////////////////////////////////////////////////
- (BOOL)isImplemented:(SEL)aSelector {
for (NSString *selectorValue in self.implementedSelectors) {
SEL storedSelector = NSSelectorFromString(selectorValue);
if (sel_isEqual(aSelector, storedSelector)) {
return YES;
}
}
return NO;
}
//////////////////////////////////////////////////////////////
#pragma mark overridden
//////////////////////////////////////////////////////////////
- (BOOL)respondsToSelector:(SEL)aSelector {
if ([self isImplemented:aSelector]) {
return YES;
} else {
return [super respondsToSelector:aSelector];
}
}
@end
讓我問一個問題作爲回報。當被問及是否響應可選方法時,爲什麼模擬應該返回NO。畢竟,這個方法是協議的一部分。 是否可以模擬實現該協議的類?如果這個類沒有實現可選方法,那麼模擬會做你期望的。 – 2012-08-13 10:30:04
原因是我想測試一個類,當它有一個沒有實現可選委託方法的委託時,它的行爲是正確的。 – extremeboredom 2012-08-13 14:07:58