Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potential solution for testing optional methods on protocol mocks where we want to control -respondsToSele… #250

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions Source/OCMock/OCMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

+ (id)mockForClass:(Class)aClass;
+ (id)mockForProtocol:(Protocol *)aProtocol;
+ (id)respondingMockForProtocol:(Protocol *)aProtocol;
+ (id)partialMockForObject:(NSObject *)anObject;

+ (id)niceMockForClass:(Class)aClass;
Expand Down
5 changes: 5 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)respondingMockForProtocol:(Protocol *)aProtocol
{
return [[[OCRespondingProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
}

+ (id)partialMockForObject:(NSObject *)anObject
{
return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
Expand Down
2 changes: 2 additions & 0 deletions Source/OCMock/OCProtocolMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@

@end

@interface OCRespondingProtocolMockObject : OCProtocolMockObject
@end
32 changes: 30 additions & 2 deletions Source/OCMock/OCProtocolMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,25 @@ - (NSString *)description

#pragma mark Proxy API

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector isRequired:(BOOL *)required
{
struct { BOOL isRequired; BOOL isInstance; } opts[4] = { {YES, YES}, {NO, YES}, {YES, NO}, {NO, NO} };
for(int i = 0; i < 4; i++)
{
struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, opts[i].isRequired, opts[i].isInstance);
if(methodDescription.name != NULL)
if(methodDescription.name != NULL) {
if (required) *required = opts[i].isRequired;
return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
}
}
return nil;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [self methodSignatureForSelector:aSelector isRequired:NULL];
}

- (BOOL)conformsToProtocol:(Protocol *)aProtocol
{
return protocol_conformsToProtocol(mockedProtocol, aProtocol);
Expand All @@ -61,3 +68,24 @@ - (BOOL)respondsToSelector:(SEL)selector
}

@end

@implementation OCRespondingProtocolMockObject

- (BOOL)respondsToSelector:(SEL)aSelector
{
BOOL required;
NSMethodSignature *sig = [self methodSignatureForSelector:aSelector isRequired:&required];
return (sig && required) || [self handleSelector:aSelector];
}

- (void)stopMocking
{
expectationOrderMatters = NO;
[stubs release]; stubs = [[NSMutableArray alloc] init];
[expectations release]; expectations = [[NSMutableArray alloc] init];
[exceptions release]; exceptions = [[NSMutableArray alloc] init];
[invocations release]; invocations = [[NSMutableArray alloc] init];
[super stopMocking];
}

@end
22 changes: 22 additions & 0 deletions Source/OCMockTests/OCMockObjectProtocolMocksTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,26 @@ - (void)testRefusesToCreateProtocolMockForNilProtocol
XCTAssertThrows(OCMProtocolMock(nil));
}

- (void)testRespondingMockProtocol
{
id mock = [OCMockObject respondingMockForProtocol:@protocol(TestProtocol)];
XCTAssertTrue([mock respondsToSelector:@selector(primitiveValue)]);
XCTAssertFalse([mock respondsToSelector:@selector(objectValue)]);
[[mock expect] objectValue];
XCTAssertTrue([mock respondsToSelector:@selector(objectValue)]);
[mock objectValue];
XCTAssertFalse([mock respondsToSelector:@selector(objectValue)]);

[[mock expect] objectValue];
XCTAssertTrue([mock respondsToSelector:@selector(objectValue)]);
[mock stopMocking];
XCTAssertFalse([mock respondsToSelector:@selector(objectValue)]);

[[mock expect] objectValue];
[[mock reject] objectValue];
XCTAssertTrue([mock respondsToSelector:@selector(objectValue)]);
[mock objectValue];
XCTAssertTrue([mock respondsToSelector:@selector(objectValue)]);
}

@end