Skip to content

Commit

Permalink
Implemented mocking class with one or multiple protocols.
Browse files Browse the repository at this point in the history
  • Loading branch information
tarbayev committed Aug 25, 2016
1 parent 8558a08 commit bfa3496
Show file tree
Hide file tree
Showing 20 changed files with 508 additions and 179 deletions.
26 changes: 14 additions & 12 deletions Source/OCMock.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
objects = {

/* Begin PBXBuildFile section */
012412861D5A0B31003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
012412871D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
012412881D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
012412891D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
012412861D5A0B31003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
012412871D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
012412881D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
012412891D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
030EF0B614632FD000B04273 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 030EF0B414632FD000B04273 /* InfoPlist.strings */; };
031E50581BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
031E50591BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
Expand Down Expand Up @@ -350,8 +350,9 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
012412841D5A0B28003B75B8 /* OCProtocolProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCProtocolProxy.h; sourceTree = "<group>"; };
012412851D5A0B28003B75B8 /* OCProtocolProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCProtocolProxy.m; sourceTree = "<group>"; };
012412841D5A0B28003B75B8 /* OCProtocolsProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCProtocolsProxy.h; sourceTree = "<group>"; };
012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCProtocolsProxy.m; sourceTree = "<group>"; };
019DD2401D6F4753001055C3 /* TestProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestProtocol.h; sourceTree = "<group>"; };
030EF0A814632FD000B04273 /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; };
030EF0B314632FD000B04273 /* OCMock-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OCMock-Info.plist"; sourceTree = "<group>"; };
030EF0B514632FD000B04273 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
Expand Down Expand Up @@ -604,6 +605,7 @@
03565A3318F0566F003AE91E /* OCMockTests */ = {
isa = PBXGroup;
children = (
019DD2401D6F4753001055C3 /* TestProtocol.h */,
2FA2822E19948FC997965267 /* OCMockObjectTests.m */,
03AC5C1416DF9FA500D82ECD /* OCMockObjectPartialMocksTests.m */,
039F91C516EFB493006C3D70 /* OCMockObjectClassMethodMockingTests.m */,
Expand Down Expand Up @@ -666,8 +668,8 @@
03B31619146334040052CD09 /* Invocation Actions */,
03B3161A146334320052CD09 /* Argument Constraints and Actions */,
037ECD5618FB0D2E00AF0E4C /* Helper */,
012412841D5A0B28003B75B8 /* OCProtocolProxy.h */,
012412851D5A0B28003B75B8 /* OCProtocolProxy.m */,
012412841D5A0B28003B75B8 /* OCProtocolsProxy.h */,
012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */,
);
name = "Core Mocks";
sourceTree = "<group>";
Expand Down Expand Up @@ -1190,7 +1192,7 @@
03B315E3146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
03B315E8146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
03B315ED146333C00052CD09 /* OCMockObject.m in Sources */,
012412861D5A0B31003B75B8 /* OCProtocolProxy.m in Sources */,
012412861D5A0B31003B75B8 /* OCProtocolsProxy.m in Sources */,
03B315F2146333C00052CD09 /* OCMStubRecorder.m in Sources */,
03B315F7146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
03B315FC146333C00052CD09 /* OCMRealObjectForwarder.m in Sources */,
Expand Down Expand Up @@ -1231,7 +1233,7 @@
03B315E0146333BF0052CD09 /* OCMIndirectReturnValueProvider.m in Sources */,
03B315E5146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
03B315EA146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
012412871D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
012412871D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
03B315EF146333C00052CD09 /* OCMockObject.m in Sources */,
03B315F4146333C00052CD09 /* OCMStubRecorder.m in Sources */,
03B315F9146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
Expand Down Expand Up @@ -1298,7 +1300,7 @@
817EB1241BD765130047E85A /* OCMBoxedReturnValueProvider.m in Sources */,
817EB1251BD765130047E85A /* OCMExceptionReturnValueProvider.m in Sources */,
817EB1261BD765130047E85A /* OCMIndirectReturnValueProvider.m in Sources */,
012412891D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
012412891D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
817EB1271BD765130047E85A /* OCMNotificationPoster.m in Sources */,
817EB1281BD765130047E85A /* OCMReturnValueProvider.m in Sources */,
817EB1291BD765130047E85A /* OCMLocation.m in Sources */,
Expand Down Expand Up @@ -1364,7 +1366,7 @@
F0B951191B0080EC00942C38 /* OCMBoxedReturnValueProvider.m in Sources */,
F0B9511A1B0080EC00942C38 /* OCMExceptionReturnValueProvider.m in Sources */,
F0B9511B1B0080EC00942C38 /* OCMIndirectReturnValueProvider.m in Sources */,
012412881D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
012412881D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
F0B9511C1B0080EC00942C38 /* OCMNotificationPoster.m in Sources */,
F0B9511D1B0080EC00942C38 /* OCMReturnValueProvider.m in Sources */,
F0B9511E1B0080EC00942C38 /* OCMLocation.m in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion Source/OCMock/OCClassMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Class originalMetaClass;
}

- (id)initWithClass:(Class)aClass;
- (id)initWithClass:(Class)aClass protocols:(NSArray *)protocols;

- (Class)mockedClass;
- (Class)mockObjectClass; // since -class returns the mockedClass
Expand Down
36 changes: 29 additions & 7 deletions Source/OCMock/OCClassMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,44 @@
#import "OCMFunctionsPrivate.h"
#import "OCMInvocationStub.h"
#import "NSMethodSignature+OCMAdditions.h"
#import "OCProtocolsProxy.h"

@implementation OCClassMockObject
{
OCProtocolsProxy *protocolsProxy;
}

#pragma mark Initialisers, description, accessors, etc.

- (id)initWithClass:(Class)aClass
- (id)initWithClass:(Class)aClass protocols:(NSArray *)protocols
{
NSParameterAssert(aClass != nil);
[super init];
mockedClass = aClass;
[super init];
mockedClass = aClass;
protocolsProxy = [[OCProtocolsProxy alloc] initWithProtocols:protocols];

[self prepareClassForClassMethodMocking];
return self;
return self;
}

- (void)dealloc
{
[self stopMocking];
[protocolsProxy release];
[super dealloc];
}

- (NSString *)description
{
return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)];
NSArray *protocolNames = [protocolsProxy protocolNames];

if (protocolNames) {
return [NSString stringWithFormat:@"OCMockObject(%@ <%@>)",
NSStringFromClass(mockedClass),
[protocolNames componentsJoinedByString:@", "]];
}

return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)];
}

- (Class)mockedClass
Expand Down Expand Up @@ -186,10 +201,17 @@ - (void)initializeForClassObject
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *signature = [mockedClass instanceMethodSignatureForSelector:aSelector];

if(signature == nil)
{
signature = [NSMethodSignature signatureForDynamicPropertyAccessedWithSelector:aSelector inClass:mockedClass];
}

if(signature == nil)
{
signature = [protocolsProxy methodSignatureForSelector:aSelector];
}

return signature;
}

Expand All @@ -205,7 +227,7 @@ - (Class)class

- (BOOL)respondsToSelector:(SEL)selector
{
return [mockedClass instancesRespondToSelector:selector];
return [mockedClass instancesRespondToSelector:selector] || [protocolsProxy respondsToSelector:selector];
}

- (BOOL)isKindOfClass:(Class)aClass
Expand All @@ -215,7 +237,7 @@ - (BOOL)isKindOfClass:(Class)aClass

- (BOOL)conformsToProtocol:(Protocol *)aProtocol
{
return class_conformsToProtocol(mockedClass, aProtocol);
return class_conformsToProtocol(mockedClass, aProtocol) || [protocolsProxy conformsToProtocol:aProtocol];
}

@end
Expand Down
16 changes: 12 additions & 4 deletions Source/OCMock/OCMock.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,22 @@
#import <OCMock/NSNotificationCenter+OCMAdditions.h>
#import <OCMock/OCMFunctions.h>

#define _OCMNilProtocol() nil
#define _OCM_OCMProtocols(...) __VA_ARGS__, nil

#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
#define _OCMConcatFirstTwoArgs(arg1, arg2, ...) arg1 ## arg2
#define _OCMCountProtocolsArgChooser(...) _OCMConcatFirstTwoArgs(__VA_ARGS__)

#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
#define _OCMProtocols() NilProtocol
#define _OCMProtocolsArgChooser(...) _OCMCountProtocolsArgChooser(_OCM, _OCMProtocols , ##__VA_ARGS__ ())

#define OCMProtocolMock(protocol...) [OCMockObject niceMockForProtocols:protocol]
#define OCMClassMock(cls, protocol...) [OCMockObject niceMockForClass:cls protocols:_OCMProtocolsArgChooser(protocol)(protocol)]

#define OCMStrictProtocolMock(protocol...) [OCMockObject mockForProtocols:protocol]
#define OCMStrictClassMock(cls, protocol...) [OCMockObject mockForClass:cls protocols:_OCMProtocolsArgChooser(protocol)(protocol)]

#define OCMProtocolMock(protocol...) [OCMockObject niceMockForProtocols:protocol, nil]

#define OCMStrictProtocolMock(protocol...) [OCMockObject mockForProtocols:protocol, nil]

#define OCMPartialMock(obj) [OCMockObject partialMockForObject:obj]

Expand Down
8 changes: 4 additions & 4 deletions Source/OCMock/OCMockObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
NSMutableArray *invocations;
}

+ (id)mockForClass:(Class)aClass;
+ (id)mockForProtocols:(Protocol *)aProtocol, ...;
+ (id)mockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ... NS_REQUIRES_NIL_TERMINATION;
+ (id)mockForProtocols:(Protocol *)aProtocol, ... NS_REQUIRES_NIL_TERMINATION;
+ (id)partialMockForObject:(NSObject *)anObject;

+ (id)niceMockForClass:(Class)aClass;
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...;
+ (id)niceMockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ... NS_REQUIRES_NIL_TERMINATION;
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ... NS_REQUIRES_NIL_TERMINATION;

+ (id)observerMock;

Expand Down
45 changes: 30 additions & 15 deletions Source/OCMock/OCMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,49 +44,68 @@ + (void)initialize

#pragma mark Factory methods

+ (id)mockForClass:(Class)aClass
+ (id)mockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...
{
return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
va_list protocolsList;
va_start(protocolsList, aProtocol);

NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];

va_end(protocolsList);

return [[[OCClassMockObject alloc] initWithClass:aClass protocols:protocols] autorelease];
}

+ (id)mockForProtocols:(Protocol *)aProtocol, ...
{
va_list protocolsList;
va_start(protocolsList, aProtocol);

id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];

va_end(protocolsList);

return mock;
return [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];
}

+ (id)partialMockForObject:(NSObject *)anObject
{
return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
}


+ (id)niceMockForClass:(Class)aClass
+ (id)niceMockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...
{
return [self _makeNice:[self mockForClass:aClass]];
va_list protocolsList;
va_start(protocolsList, aProtocol);

NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];

va_end(protocolsList);

id mock = [[[OCClassMockObject alloc] initWithClass:aClass protocols:protocols] autorelease];
return [self _makeNice:mock];
}

+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...
{
va_list protocolsList;
va_start(protocolsList, aProtocol);

id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];

va_end(protocolsList);

id mock = [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];

return [self _makeNice:mock];
}

+ (id)_mockForProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsList
+ (NSArray *)_arrayOfProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsList
{
NSParameterAssert(aProtocol != nil);
if (!aProtocol)
{
return nil;
}

NSMutableArray *protocols = [NSMutableArray new];

Expand All @@ -96,11 +115,7 @@ + (id)_mockForProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsLi
aProtocol = va_arg(protocolsList, typeof(aProtocol));
}

id result = [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];

[protocols release];

return result;
return [protocols autorelease];
}

+ (id)_makeNice:(OCMockObject *)mock
Expand Down
2 changes: 1 addition & 1 deletion Source/OCMock/OCPartialMockObject.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ - (id)initWithObject:(NSObject *)anObject
{
NSParameterAssert(anObject != nil);
[self assertClassIsSupported:[anObject class]];
[super initWithClass:[anObject class]];
[super initWithClass:[anObject class] protocols:nil];
realObject = [anObject retain];
[self prepareObjectForInstanceMethodMocking];
return self;
Expand Down

0 comments on commit bfa3496

Please sign in to comment.