diff --git a/Source/OCMock/OCMockMacros.h b/Source/OCMock/OCMockMacros.h index 22535572..c87577d1 100644 --- a/Source/OCMock/OCMockMacros.h +++ b/Source/OCMock/OCMockMacros.h @@ -27,8 +27,12 @@ #define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol] +#define OCMProtocolsMock(protocols) [OCMockObject niceMockForProtocols:protocols] + #define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol] +#define OCMStrictProtocolsMock(protocols) [OCMockObject mockForProtocol:protocols] + #define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj] #define OCMObserverMock() [OCMockObject observerMock] diff --git a/Source/OCMock/OCMockObject.h b/Source/OCMock/OCMockObject.h index f5739716..33fff907 100644 --- a/Source/OCMock/OCMockObject.h +++ b/Source/OCMock/OCMockObject.h @@ -36,10 +36,12 @@ + (id)mockForClass:(Class)aClass; + (id)mockForProtocol:(Protocol *)aProtocol; ++ (id)mockForProtocols:(NSArray*)aProtocols; + (id)partialMockForObject:(NSObject *)anObject; + (id)niceMockForClass:(Class)aClass; + (id)niceMockForProtocol:(Protocol *)aProtocol; ++ (id)niceMockForProtocols:(NSArray *)aProtocols; + (id)observerMock __deprecated_msg("Please use XCTNSNotificationExpectation instead."); diff --git a/Source/OCMock/OCMockObject.m b/Source/OCMock/OCMockObject.m index d78cba44..b54d17a7 100644 --- a/Source/OCMock/OCMockObject.m +++ b/Source/OCMock/OCMockObject.m @@ -53,6 +53,11 @@ + (id)mockForProtocol:(Protocol *)aProtocol return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease]; } ++ (id)mockForProtocols:(NSArray *)aProtocol +{ + return [[[OCProtocolMockObject alloc] initWithProtocols:aProtocol] autorelease]; +} + + (id)partialMockForObject:(NSObject *)anObject { return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease]; @@ -69,6 +74,11 @@ + (id)niceMockForProtocol:(Protocol *)aProtocol return [self _makeNice:[self mockForProtocol:aProtocol]]; } ++ (id)niceMockForProtocols:(NSArray *)aProtocols +{ + return [self _makeNice:[self mockForProtocols:aProtocols]]; +} + + (id)_makeNice:(OCMockObject *)mock { diff --git a/Source/OCMock/OCProtocolMockObject.h b/Source/OCMock/OCProtocolMockObject.h index a6bac51f..4f71d9d7 100644 --- a/Source/OCMock/OCProtocolMockObject.h +++ b/Source/OCMock/OCProtocolMockObject.h @@ -18,9 +18,10 @@ @interface OCProtocolMockObject : OCMockObject { - Protocol *mockedProtocol; + NSArray *mockedProtocols; } - (id)initWithProtocol:(Protocol *)aProtocol; +- (id)initWithProtocols:(NSArray *)aProtocols; @end diff --git a/Source/OCMock/OCProtocolMockObject.m b/Source/OCMock/OCProtocolMockObject.m index 76f44f15..892961c8 100644 --- a/Source/OCMock/OCProtocolMockObject.m +++ b/Source/OCMock/OCProtocolMockObject.m @@ -22,20 +22,44 @@ @implementation OCProtocolMockObject #pragma mark Initialisers, description, accessors, etc. -- (id)initWithProtocol:(Protocol *)aProtocol +- (id)initWithProtocols:(NSArray *)aProtocols { - if(aProtocol == nil) + if(aProtocols == nil) + [NSException raise:NSInvalidArgumentException format:@"Protocols cannot be nil."]; + if([aProtocols count] == 0) + [NSException raise:NSInvalidArgumentException format:@"Protocols cannot be empty."]; + for (Protocol *protocol in aProtocols) { + if(protocol == nil) [NSException raise:NSInvalidArgumentException format:@"Protocol cannot be nil."]; + } [super init]; - mockedProtocol = aProtocol; + mockedProtocols = aProtocols; return self; } +- (id)initWithProtocol:(Protocol *)aProtocol +{ + if(aProtocol == nil) + [NSException raise:NSInvalidArgumentException format:@"Protocol cannot be nil."]; + + return [self initWithProtocols:@[aProtocol]]; +} + - (NSString *)description { - const char *name = protocol_getName(mockedProtocol); + if ([mockedProtocols count] == 1) { + const char *name = protocol_getName(mockedProtocols[0]); return [NSString stringWithFormat:@"OCProtocolMockObject(%s)", name]; + } + + NSMutableString* string = [[NSMutableString alloc] initWithString:@"OCProtoolMockObject(["]; + for (int i = 0; i < [mockedProtocols count]; i++) { + if (i > 0) [string appendString:@", "]; + [string appendFormat:@"%s", protocol_getName(mockedProtocols[i])]; + } + [string appendString:@"])"]; + return string; } #pragma mark Proxy API @@ -45,21 +69,32 @@ - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector struct { BOOL isRequired; BOOL isInstance; } opts[4] = { {YES, YES}, {NO, YES}, {YES, NO}, {NO, NO} }; for(int i = 0; i < 4; i++) { + for (Protocol *mockedProtocol in mockedProtocols) { struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, opts[i].isRequired, opts[i].isInstance); if(methodDescription.name != NULL) - return [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + return [NSMethodSignature signatureWithObjCTypes:methodDescription.types]; + } } return nil; } - (BOOL)conformsToProtocol:(Protocol *)aProtocol { - return protocol_conformsToProtocol(mockedProtocol, aProtocol); + for (Protocol *mockedProtocol in mockedProtocols) { + + if(protocol_conformsToProtocol(mockedProtocol, aProtocol)) return YES; + } + return NO; } - (BOOL)respondsToSelector:(SEL)selector { - return ([self methodSignatureForSelector:selector] != nil); + for (Protocol *mockedProtocol in mockedProtocols) { + if ([self methodSignatureForSelector:selector] != nil) { + return YES; + } + } + return NO; } @end