diff --git a/Source/OCMock/OCMockObject.h b/Source/OCMock/OCMockObject.h index 58df67d7..42ed5754 100644 --- a/Source/OCMock/OCMockObject.h +++ b/Source/OCMock/OCMockObject.h @@ -35,6 +35,7 @@ + (id)mockForClass:(Class)aClass; + (id)mockForProtocol:(Protocol *)aProtocol; ++ (id)respondingMockForProtocol:(Protocol *)aProtocol; + (id)partialMockForObject:(NSObject *)anObject; + (id)niceMockForClass:(Class)aClass; diff --git a/Source/OCMock/OCMockObject.m b/Source/OCMock/OCMockObject.m index cf9d0c5c..1c4acc57 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)respondingMockForProtocol:(Protocol *)aProtocol +{ + return [[[OCRespondingProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease]; +} + + (id)partialMockForObject:(NSObject *)anObject { return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease]; diff --git a/Source/OCMock/OCProtocolMockObject.h b/Source/OCMock/OCProtocolMockObject.h index 9a102b3f..b3f36965 100644 --- a/Source/OCMock/OCProtocolMockObject.h +++ b/Source/OCMock/OCProtocolMockObject.h @@ -25,3 +25,5 @@ @end +@interface OCRespondingProtocolMockObject : OCProtocolMockObject +@end diff --git a/Source/OCMock/OCProtocolMockObject.m b/Source/OCMock/OCProtocolMockObject.m index 82f61679..1f6b2f88 100644 --- a/Source/OCMock/OCProtocolMockObject.m +++ b/Source/OCMock/OCProtocolMockObject.m @@ -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); @@ -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 diff --git a/Source/OCMockTests/OCMockObjectProtocolMocksTests.m b/Source/OCMockTests/OCMockObjectProtocolMocksTests.m index 4c4a6db2..540edb9e 100644 --- a/Source/OCMockTests/OCMockObjectProtocolMocksTests.m +++ b/Source/OCMockTests/OCMockObjectProtocolMocksTests.m @@ -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