Skip to content

Commit 51227bd

Browse files
committed
Implemented mocking class with one or multiple protocols.
1 parent 8558a08 commit 51227bd

20 files changed

+476
-159
lines changed

Source/OCMock.xcodeproj/project.pbxproj

+14-12
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10-
012412861D5A0B31003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
11-
012412871D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
12-
012412881D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
13-
012412891D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolProxy.m */; };
10+
012412861D5A0B31003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
11+
012412871D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
12+
012412881D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
13+
012412891D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */; };
1414
030EF0B614632FD000B04273 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 030EF0B414632FD000B04273 /* InfoPlist.strings */; };
1515
031E50581BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
1616
031E50591BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
@@ -350,8 +350,9 @@
350350
/* End PBXContainerItemProxy section */
351351

352352
/* Begin PBXFileReference section */
353-
012412841D5A0B28003B75B8 /* OCProtocolProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCProtocolProxy.h; sourceTree = "<group>"; };
354-
012412851D5A0B28003B75B8 /* OCProtocolProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCProtocolProxy.m; sourceTree = "<group>"; };
353+
012412841D5A0B28003B75B8 /* OCProtocolsProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OCProtocolsProxy.h; sourceTree = "<group>"; };
354+
012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OCProtocolsProxy.m; sourceTree = "<group>"; };
355+
019DD2401D6F4753001055C3 /* TestProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestProtocol.h; sourceTree = "<group>"; };
355356
030EF0A814632FD000B04273 /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; };
356357
030EF0B314632FD000B04273 /* OCMock-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OCMock-Info.plist"; sourceTree = "<group>"; };
357358
030EF0B514632FD000B04273 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -604,6 +605,7 @@
604605
03565A3318F0566F003AE91E /* OCMockTests */ = {
605606
isa = PBXGroup;
606607
children = (
608+
019DD2401D6F4753001055C3 /* TestProtocol.h */,
607609
2FA2822E19948FC997965267 /* OCMockObjectTests.m */,
608610
03AC5C1416DF9FA500D82ECD /* OCMockObjectPartialMocksTests.m */,
609611
039F91C516EFB493006C3D70 /* OCMockObjectClassMethodMockingTests.m */,
@@ -666,8 +668,8 @@
666668
03B31619146334040052CD09 /* Invocation Actions */,
667669
03B3161A146334320052CD09 /* Argument Constraints and Actions */,
668670
037ECD5618FB0D2E00AF0E4C /* Helper */,
669-
012412841D5A0B28003B75B8 /* OCProtocolProxy.h */,
670-
012412851D5A0B28003B75B8 /* OCProtocolProxy.m */,
671+
012412841D5A0B28003B75B8 /* OCProtocolsProxy.h */,
672+
012412851D5A0B28003B75B8 /* OCProtocolsProxy.m */,
671673
);
672674
name = "Core Mocks";
673675
sourceTree = "<group>";
@@ -1190,7 +1192,7 @@
11901192
03B315E3146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
11911193
03B315E8146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
11921194
03B315ED146333C00052CD09 /* OCMockObject.m in Sources */,
1193-
012412861D5A0B31003B75B8 /* OCProtocolProxy.m in Sources */,
1195+
012412861D5A0B31003B75B8 /* OCProtocolsProxy.m in Sources */,
11941196
03B315F2146333C00052CD09 /* OCMStubRecorder.m in Sources */,
11951197
03B315F7146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
11961198
03B315FC146333C00052CD09 /* OCMRealObjectForwarder.m in Sources */,
@@ -1231,7 +1233,7 @@
12311233
03B315E0146333BF0052CD09 /* OCMIndirectReturnValueProvider.m in Sources */,
12321234
03B315E5146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
12331235
03B315EA146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
1234-
012412871D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
1236+
012412871D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
12351237
03B315EF146333C00052CD09 /* OCMockObject.m in Sources */,
12361238
03B315F4146333C00052CD09 /* OCMStubRecorder.m in Sources */,
12371239
03B315F9146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
@@ -1298,7 +1300,7 @@
12981300
817EB1241BD765130047E85A /* OCMBoxedReturnValueProvider.m in Sources */,
12991301
817EB1251BD765130047E85A /* OCMExceptionReturnValueProvider.m in Sources */,
13001302
817EB1261BD765130047E85A /* OCMIndirectReturnValueProvider.m in Sources */,
1301-
012412891D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
1303+
012412891D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
13021304
817EB1271BD765130047E85A /* OCMNotificationPoster.m in Sources */,
13031305
817EB1281BD765130047E85A /* OCMReturnValueProvider.m in Sources */,
13041306
817EB1291BD765130047E85A /* OCMLocation.m in Sources */,
@@ -1364,7 +1366,7 @@
13641366
F0B951191B0080EC00942C38 /* OCMBoxedReturnValueProvider.m in Sources */,
13651367
F0B9511A1B0080EC00942C38 /* OCMExceptionReturnValueProvider.m in Sources */,
13661368
F0B9511B1B0080EC00942C38 /* OCMIndirectReturnValueProvider.m in Sources */,
1367-
012412881D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
1369+
012412881D5A0B32003B75B8 /* OCProtocolsProxy.m in Sources */,
13681370
F0B9511C1B0080EC00942C38 /* OCMNotificationPoster.m in Sources */,
13691371
F0B9511D1B0080EC00942C38 /* OCMReturnValueProvider.m in Sources */,
13701372
F0B9511E1B0080EC00942C38 /* OCMLocation.m in Sources */,

Source/OCMock/OCClassMockObject.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
Class originalMetaClass;
2323
}
2424

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

2727
- (Class)mockedClass;
2828
- (Class)mockObjectClass; // since -class returns the mockedClass

Source/OCMock/OCClassMockObject.m

+29-7
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,44 @@
2020
#import "OCMFunctionsPrivate.h"
2121
#import "OCMInvocationStub.h"
2222
#import "NSMethodSignature+OCMAdditions.h"
23+
#import "OCProtocolsProxy.h"
2324

2425
@implementation OCClassMockObject
26+
{
27+
OCProtocolsProxy *protocolsProxy;
28+
}
2529

2630
#pragma mark Initialisers, description, accessors, etc.
2731

28-
- (id)initWithClass:(Class)aClass
32+
- (id)initWithClass:(Class)aClass protocols:(NSArray *)protocols
2933
{
3034
NSParameterAssert(aClass != nil);
31-
[super init];
32-
mockedClass = aClass;
35+
[super init];
36+
mockedClass = aClass;
37+
protocolsProxy = [[OCProtocolsProxy alloc] initWithProtocols:protocols];
38+
3339
[self prepareClassForClassMethodMocking];
34-
return self;
40+
return self;
3541
}
3642

3743
- (void)dealloc
3844
{
3945
[self stopMocking];
46+
[protocolsProxy release];
4047
[super dealloc];
4148
}
4249

4350
- (NSString *)description
4451
{
45-
return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)];
52+
NSArray *protocolNames = [protocolsProxy protocolNames];
53+
54+
if (protocolNames) {
55+
return [NSString stringWithFormat:@"OCMockObject(%@ <%@>)",
56+
NSStringFromClass(mockedClass),
57+
[protocolNames componentsJoinedByString:@", "]];
58+
}
59+
60+
return [NSString stringWithFormat:@"OCMockObject(%@)", NSStringFromClass(mockedClass)];
4661
}
4762

4863
- (Class)mockedClass
@@ -186,10 +201,17 @@ - (void)initializeForClassObject
186201
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
187202
{
188203
NSMethodSignature *signature = [mockedClass instanceMethodSignatureForSelector:aSelector];
204+
189205
if(signature == nil)
190206
{
191207
signature = [NSMethodSignature signatureForDynamicPropertyAccessedWithSelector:aSelector inClass:mockedClass];
192208
}
209+
210+
if(signature == nil)
211+
{
212+
signature = [protocolsProxy methodSignatureForSelector:aSelector];
213+
}
214+
193215
return signature;
194216
}
195217

@@ -205,7 +227,7 @@ - (Class)class
205227

206228
- (BOOL)respondsToSelector:(SEL)selector
207229
{
208-
return [mockedClass instancesRespondToSelector:selector];
230+
return [mockedClass instancesRespondToSelector:selector] || [protocolsProxy respondsToSelector:selector];
209231
}
210232

211233
- (BOOL)isKindOfClass:(Class)aClass
@@ -215,7 +237,7 @@ - (BOOL)isKindOfClass:(Class)aClass
215237

216238
- (BOOL)conformsToProtocol:(Protocol *)aProtocol
217239
{
218-
return class_conformsToProtocol(mockedClass, aProtocol);
240+
return class_conformsToProtocol(mockedClass, aProtocol) || [protocolsProxy conformsToProtocol:aProtocol];
219241
}
220242

221243
@end

Source/OCMock/OCMock.h

+10-2
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,18 @@
2424
#import <OCMock/NSNotificationCenter+OCMAdditions.h>
2525
#import <OCMock/OCMFunctions.h>
2626

27+
#define _OCMNilProtocol() nil
28+
#define _OCM_OCMProtocols(...) __VA_ARGS__
2729

28-
#define OCMClassMock(cls) [OCMockObject niceMockForClass:cls]
30+
#define _OCMConcatFirstTwoArgs(arg1, arg2, ...) arg1 ## arg2
31+
#define _OCMCountProtocolsArgChooser(...) _OCMConcatFirstTwoArgs(__VA_ARGS__)
2932

30-
#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
33+
#define _OCMProtocols() NilProtocol
34+
#define _OCMProtocolsArgChooser(...) _OCMCountProtocolsArgChooser(_OCM, _OCMProtocols , ##__VA_ARGS__ ())
35+
36+
#define OCMClassMock(cls, protocol...) [OCMockObject niceMockForClass:cls protocols:_OCMProtocolsArgChooser(protocol)(protocol)]
37+
38+
#define OCMStrictClassMock(cls, protocol...) [OCMockObject mockForClass:cls protocols:_OCMProtocolsArgChooser(protocol)(protocol)]
3139

3240
#define OCMProtocolMock(protocol...) [OCMockObject niceMockForProtocols:protocol]
3341

Source/OCMock/OCMockObject.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@
3333
NSMutableArray *invocations;
3434
}
3535

36-
+ (id)mockForClass:(Class)aClass;
36+
+ (id)mockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...;
3737
+ (id)mockForProtocols:(Protocol *)aProtocol, ...;
3838
+ (id)partialMockForObject:(NSObject *)anObject;
3939

40-
+ (id)niceMockForClass:(Class)aClass;
40+
+ (id)niceMockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...;
4141
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...;
4242

4343
+ (id)observerMock;

Source/OCMock/OCMockObject.m

+30-15
Original file line numberDiff line numberDiff line change
@@ -44,49 +44,68 @@ + (void)initialize
4444

4545
#pragma mark Factory methods
4646

47-
+ (id)mockForClass:(Class)aClass
47+
+ (id)mockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...
4848
{
49-
return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
49+
va_list protocolsList;
50+
va_start(protocolsList, aProtocol);
51+
52+
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];
53+
54+
va_end(protocolsList);
55+
56+
return [[[OCClassMockObject alloc] initWithClass:aClass protocols:protocols] autorelease];
5057
}
5158

5259
+ (id)mockForProtocols:(Protocol *)aProtocol, ...
5360
{
5461
va_list protocolsList;
5562
va_start(protocolsList, aProtocol);
5663

57-
id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
64+
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];
5865

5966
va_end(protocolsList);
6067

61-
return mock;
68+
return [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];
6269
}
6370

6471
+ (id)partialMockForObject:(NSObject *)anObject
6572
{
6673
return [[[OCPartialMockObject alloc] initWithObject:anObject] autorelease];
6774
}
6875

69-
70-
+ (id)niceMockForClass:(Class)aClass
76+
+ (id)niceMockForClass:(Class)aClass protocols:(Protocol *)aProtocol, ...
7177
{
72-
return [self _makeNice:[self mockForClass:aClass]];
78+
va_list protocolsList;
79+
va_start(protocolsList, aProtocol);
80+
81+
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];
82+
83+
va_end(protocolsList);
84+
85+
id mock = [[[OCClassMockObject alloc] initWithClass:aClass protocols:protocols] autorelease];
86+
return [self _makeNice:mock];
7387
}
7488

7589
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...
7690
{
7791
va_list protocolsList;
7892
va_start(protocolsList, aProtocol);
7993

80-
id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
94+
NSArray *protocols = [self _arrayOfProtocol:aProtocol otherProtocols:protocolsList];
8195

8296
va_end(protocolsList);
8397

98+
id mock = [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];
99+
84100
return [self _makeNice:mock];
85101
}
86102

87-
+ (id)_mockForProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsList
103+
+ (NSArray *)_arrayOfProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsList
88104
{
89-
NSParameterAssert(aProtocol != nil);
105+
if (!aProtocol)
106+
{
107+
return nil;
108+
}
90109

91110
NSMutableArray *protocols = [NSMutableArray new];
92111

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

99-
id result = [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];
100-
101-
[protocols release];
102-
103-
return result;
118+
return [protocols autorelease];
104119
}
105120

106121
+ (id)_makeNice:(OCMockObject *)mock

Source/OCMock/OCPartialMockObject.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ - (id)initWithObject:(NSObject *)anObject
3131
{
3232
NSParameterAssert(anObject != nil);
3333
[self assertClassIsSupported:[anObject class]];
34-
[super initWithClass:[anObject class]];
34+
[super initWithClass:[anObject class] protocols:nil];
3535
realObject = [anObject retain];
3636
[self prepareObjectForInstanceMethodMocking];
3737
return self;

Source/OCMock/OCProtocolMockObject.m

+10-33
Original file line numberDiff line numberDiff line change
@@ -17,76 +17,53 @@
1717
#import <objc/runtime.h>
1818
#import "NSMethodSignature+OCMAdditions.h"
1919
#import "OCProtocolMockObject.h"
20-
#import "OCProtocolProxy.h"
20+
#import "OCProtocolsProxy.h"
2121

2222
@implementation OCProtocolMockObject
2323
{
24-
NSArray *protocolProxies;
24+
OCProtocolsProxy *protocolsProxy;
2525
}
2626

2727
#pragma mark Initialisers, description, accessors, etc.
2828

2929
- (id)initWithProtocols:(NSArray *)protocols
3030
{
31-
[super init];
32-
33-
NSMutableArray *proxies = [NSMutableArray new];
31+
NSCParameterAssert(protocols != nil);
3432

35-
for(Protocol *aProtocol in protocols)
36-
{
37-
OCProtocolProxy *protocolProxy = [[OCProtocolProxy alloc] initWithProtocol:aProtocol];
38-
[proxies addObject:protocolProxy];
39-
[protocolProxy release];
40-
}
33+
[super init];
4134

42-
protocolProxies = proxies;
35+
protocolsProxy = [[OCProtocolsProxy alloc] initWithProtocols:protocols];
4336

4437
return self;
4538
}
4639

4740
- (void)dealloc
4841
{
49-
[protocolProxies release];
42+
[protocolsProxy release];
5043
[super dealloc];
5144
}
5245

5346
- (NSString *)description
5447
{
55-
NSArray *protocolNames = [protocolProxies valueForKey:NSStringFromSelector(@selector(protocolName))];
48+
NSArray *protocolNames = [protocolsProxy protocolNames];
5649
return [NSString stringWithFormat:@"OCMockObject(%@)", [protocolNames componentsJoinedByString:@", "]];
5750
}
5851

5952
#pragma mark Proxy API
6053

6154
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
6255
{
63-
for(OCProtocolProxy *protocolProxy in protocolProxies)
64-
{
65-
NSMethodSignature *signature = [protocolProxy methodSignatureForSelector:aSelector];
66-
67-
if(signature)
68-
{
69-
return signature;
70-
}
71-
}
72-
return nil;
56+
return [protocolsProxy methodSignatureForSelector:aSelector];
7357
}
7458

7559
- (BOOL)conformsToProtocol:(Protocol *)aProtocol
7660
{
77-
for(OCProtocolProxy *protocolProxy in protocolProxies)
78-
{
79-
if([protocolProxy conformsToProtocol:aProtocol])
80-
{
81-
return YES;
82-
}
83-
}
84-
return NO;
61+
return [protocolsProxy conformsToProtocol:aProtocol];
8562
}
8663

8764
- (BOOL)respondsToSelector:(SEL)selector
8865
{
89-
return ([self methodSignatureForSelector:selector] != nil);
66+
return [protocolsProxy respondsToSelector:selector];
9067
}
9168

9269
@end

0 commit comments

Comments
 (0)