Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Source/OCMock/OCMockMacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 2 additions & 0 deletions Source/OCMock/OCMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@

+ (id)mockForClass:(Class)aClass;
+ (id)mockForProtocol:(Protocol *)aProtocol;
+ (id)mockForProtocols:(NSArray<Protocol *>*)aProtocols;
+ (id)partialMockForObject:(NSObject *)anObject;

+ (id)niceMockForClass:(Class)aClass;
+ (id)niceMockForProtocol:(Protocol *)aProtocol;
+ (id)niceMockForProtocols:(NSArray<Protocol *> *)aProtocols;

+ (id)observerMock __deprecated_msg("Please use XCTNSNotificationExpectation instead.");

Expand Down
10 changes: 10 additions & 0 deletions Source/OCMock/OCMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ + (id)mockForProtocol:(Protocol *)aProtocol
return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
}

+ (id)mockForProtocols:(NSArray<Protocol *> *)aProtocol
{
return [[[OCProtocolMockObject alloc] initWithProtocols:aProtocol] autorelease];
}

+ (id)partialMockForObject:(NSObject *)anObject
{
return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
Expand All @@ -69,6 +74,11 @@ + (id)niceMockForProtocol:(Protocol *)aProtocol
return [self _makeNice:[self mockForProtocol:aProtocol]];
}

+ (id)niceMockForProtocols:(NSArray<Protocol *> *)aProtocols
{
return [self _makeNice:[self mockForProtocols:aProtocols]];
}


+ (id)_makeNice:(OCMockObject *)mock
{
Expand Down
3 changes: 2 additions & 1 deletion Source/OCMock/OCProtocolMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

@interface OCProtocolMockObject : OCMockObject
{
Protocol *mockedProtocol;
NSArray<Protocol *> *mockedProtocols;
}

- (id)initWithProtocol:(Protocol *)aProtocol;
- (id)initWithProtocols:(NSArray<Protocol *> *)aProtocols;

@end
49 changes: 42 additions & 7 deletions Source/OCMock/OCProtocolMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,44 @@ @implementation OCProtocolMockObject

#pragma mark Initialisers, description, accessors, etc.

- (id)initWithProtocol:(Protocol *)aProtocol
- (id)initWithProtocols:(NSArray<Protocol *> *)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
Expand All @@ -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