Skip to content

Commit 8558a08

Browse files
committed
Implemented multiple protocols mocking.
1 parent 5d9028f commit 8558a08

File tree

9 files changed

+231
-40
lines changed

9 files changed

+231
-40
lines changed

Source/OCMock.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +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 */; };
1014
030EF0B614632FD000B04273 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 030EF0B414632FD000B04273 /* InfoPlist.strings */; };
1115
031E50581BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
1216
031E50591BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 031E50571BB4A56300E257C3 /* OCMBoxedReturnValueProviderTests.m */; };
@@ -346,6 +350,8 @@
346350
/* End PBXContainerItemProxy section */
347351

348352
/* 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>"; };
349355
030EF0A814632FD000B04273 /* OCMock.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OCMock.framework; sourceTree = BUILT_PRODUCTS_DIR; };
350356
030EF0B314632FD000B04273 /* OCMock-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "OCMock-Info.plist"; sourceTree = "<group>"; };
351357
030EF0B514632FD000B04273 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -660,6 +666,8 @@
660666
03B31619146334040052CD09 /* Invocation Actions */,
661667
03B3161A146334320052CD09 /* Argument Constraints and Actions */,
662668
037ECD5618FB0D2E00AF0E4C /* Helper */,
669+
012412841D5A0B28003B75B8 /* OCProtocolProxy.h */,
670+
012412851D5A0B28003B75B8 /* OCProtocolProxy.m */,
663671
);
664672
name = "Core Mocks";
665673
sourceTree = "<group>";
@@ -1182,6 +1190,7 @@
11821190
03B315E3146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
11831191
03B315E8146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
11841192
03B315ED146333C00052CD09 /* OCMockObject.m in Sources */,
1193+
012412861D5A0B31003B75B8 /* OCProtocolProxy.m in Sources */,
11851194
03B315F2146333C00052CD09 /* OCMStubRecorder.m in Sources */,
11861195
03B315F7146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
11871196
03B315FC146333C00052CD09 /* OCMRealObjectForwarder.m in Sources */,
@@ -1222,6 +1231,7 @@
12221231
03B315E0146333BF0052CD09 /* OCMIndirectReturnValueProvider.m in Sources */,
12231232
03B315E5146333BF0052CD09 /* OCMNotificationPoster.m in Sources */,
12241233
03B315EA146333BF0052CD09 /* OCMObserverRecorder.m in Sources */,
1234+
012412871D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
12251235
03B315EF146333C00052CD09 /* OCMockObject.m in Sources */,
12261236
03B315F4146333C00052CD09 /* OCMStubRecorder.m in Sources */,
12271237
03B315F9146333C00052CD09 /* OCMPassByRefSetter.m in Sources */,
@@ -1288,6 +1298,7 @@
12881298
817EB1241BD765130047E85A /* OCMBoxedReturnValueProvider.m in Sources */,
12891299
817EB1251BD765130047E85A /* OCMExceptionReturnValueProvider.m in Sources */,
12901300
817EB1261BD765130047E85A /* OCMIndirectReturnValueProvider.m in Sources */,
1301+
012412891D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
12911302
817EB1271BD765130047E85A /* OCMNotificationPoster.m in Sources */,
12921303
817EB1281BD765130047E85A /* OCMReturnValueProvider.m in Sources */,
12931304
817EB1291BD765130047E85A /* OCMLocation.m in Sources */,
@@ -1353,6 +1364,7 @@
13531364
F0B951191B0080EC00942C38 /* OCMBoxedReturnValueProvider.m in Sources */,
13541365
F0B9511A1B0080EC00942C38 /* OCMExceptionReturnValueProvider.m in Sources */,
13551366
F0B9511B1B0080EC00942C38 /* OCMIndirectReturnValueProvider.m in Sources */,
1367+
012412881D5A0B32003B75B8 /* OCProtocolProxy.m in Sources */,
13561368
F0B9511C1B0080EC00942C38 /* OCMNotificationPoster.m in Sources */,
13571369
F0B9511D1B0080EC00942C38 /* OCMReturnValueProvider.m in Sources */,
13581370
F0B9511E1B0080EC00942C38 /* OCMLocation.m in Sources */,

Source/OCMock/OCMock.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929

3030
#define OCMStrictClassMock(cls) [OCMockObject mockForClass:cls]
3131

32-
#define OCMProtocolMock(protocol) [OCMockObject niceMockForProtocol:protocol]
32+
#define OCMProtocolMock(protocol...) [OCMockObject niceMockForProtocols:protocol]
3333

34-
#define OCMStrictProtocolMock(protocol) [OCMockObject mockForProtocol:protocol]
34+
#define OCMStrictProtocolMock(protocol...) [OCMockObject mockForProtocols:protocol]
3535

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

Source/OCMock/OCMockObject.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@
3434
}
3535

3636
+ (id)mockForClass:(Class)aClass;
37-
+ (id)mockForProtocol:(Protocol *)aProtocol;
37+
+ (id)mockForProtocols:(Protocol *)aProtocol, ...;
3838
+ (id)partialMockForObject:(NSObject *)anObject;
3939

4040
+ (id)niceMockForClass:(Class)aClass;
41-
+ (id)niceMockForProtocol:(Protocol *)aProtocol;
41+
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...;
4242

4343
+ (id)observerMock;
4444

Source/OCMock/OCMockObject.m

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,16 @@ + (id)mockForClass:(Class)aClass
4949
return [[[OCClassMockObject alloc] initWithClass:aClass] autorelease];
5050
}
5151

52-
+ (id)mockForProtocol:(Protocol *)aProtocol
52+
+ (id)mockForProtocols:(Protocol *)aProtocol, ...
5353
{
54-
return [[[OCProtocolMockObject alloc] initWithProtocol:aProtocol] autorelease];
54+
va_list protocolsList;
55+
va_start(protocolsList, aProtocol);
56+
57+
id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
58+
59+
va_end(protocolsList);
60+
61+
return mock;
5562
}
5663

5764
+ (id)partialMockForObject:(NSObject *)anObject
@@ -65,11 +72,36 @@ + (id)niceMockForClass:(Class)aClass
6572
return [self _makeNice:[self mockForClass:aClass]];
6673
}
6774

68-
+ (id)niceMockForProtocol:(Protocol *)aProtocol
75+
+ (id)niceMockForProtocols:(Protocol *)aProtocol, ...
6976
{
70-
return [self _makeNice:[self mockForProtocol:aProtocol]];
77+
va_list protocolsList;
78+
va_start(protocolsList, aProtocol);
79+
80+
id mock = [self _mockForProtocol:aProtocol otherProtocols:protocolsList];
81+
82+
va_end(protocolsList);
83+
84+
return [self _makeNice:mock];
7185
}
7286

87+
+ (id)_mockForProtocol:(Protocol *)aProtocol otherProtocols:(va_list)protocolsList
88+
{
89+
NSParameterAssert(aProtocol != nil);
90+
91+
NSMutableArray *protocols = [NSMutableArray new];
92+
93+
while(aProtocol)
94+
{
95+
[protocols addObject:aProtocol];
96+
aProtocol = va_arg(protocolsList, typeof(aProtocol));
97+
}
98+
99+
id result = [[[OCProtocolMockObject alloc] initWithProtocols:protocols] autorelease];
100+
101+
[protocols release];
102+
103+
return result;
104+
}
73105

74106
+ (id)_makeNice:(OCMockObject *)mock
75107
{

Source/OCMock/OCProtocolMockObject.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,8 @@
1717
#import <OCMock/OCMockObject.h>
1818

1919
@interface OCProtocolMockObject : OCMockObject
20-
{
21-
Protocol *mockedProtocol;
22-
}
2320

24-
- (id)initWithProtocol:(Protocol *)aProtocol;
21+
- (id)initWithProtocols:(NSArray *)protocols;
2522

2623
@end
2724

Source/OCMock/OCProtocolMockObject.m

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,42 +17,71 @@
1717
#import <objc/runtime.h>
1818
#import "NSMethodSignature+OCMAdditions.h"
1919
#import "OCProtocolMockObject.h"
20+
#import "OCProtocolProxy.h"
2021

2122
@implementation OCProtocolMockObject
23+
{
24+
NSArray *protocolProxies;
25+
}
2226

2327
#pragma mark Initialisers, description, accessors, etc.
2428

25-
- (id)initWithProtocol:(Protocol *)aProtocol
29+
- (id)initWithProtocols:(NSArray *)protocols
2630
{
27-
NSParameterAssert(aProtocol != nil);
2831
[super init];
29-
mockedProtocol = aProtocol;
32+
33+
NSMutableArray *proxies = [NSMutableArray new];
34+
35+
for(Protocol *aProtocol in protocols)
36+
{
37+
OCProtocolProxy *protocolProxy = [[OCProtocolProxy alloc] initWithProtocol:aProtocol];
38+
[proxies addObject:protocolProxy];
39+
[protocolProxy release];
40+
}
41+
42+
protocolProxies = proxies;
43+
3044
return self;
3145
}
3246

47+
- (void)dealloc
48+
{
49+
[protocolProxies release];
50+
[super dealloc];
51+
}
52+
3353
- (NSString *)description
3454
{
35-
const char* name = protocol_getName(mockedProtocol);
36-
return [NSString stringWithFormat:@"OCMockObject(%s)", name];
55+
NSArray *protocolNames = [protocolProxies valueForKey:NSStringFromSelector(@selector(protocolName))];
56+
return [NSString stringWithFormat:@"OCMockObject(%@)", [protocolNames componentsJoinedByString:@", "]];
3757
}
3858

3959
#pragma mark Proxy API
4060

4161
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
4262
{
43-
struct { BOOL isRequired; BOOL isInstance; } opts[4] = { {YES, YES}, {NO, YES}, {YES, NO}, {NO, NO} };
44-
for(int i = 0; i < 4; i++)
63+
for(OCProtocolProxy *protocolProxy in protocolProxies)
4564
{
46-
struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, opts[i].isRequired, opts[i].isInstance);
47-
if(methodDescription.name != NULL)
48-
return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
65+
NSMethodSignature *signature = [protocolProxy methodSignatureForSelector:aSelector];
66+
67+
if(signature)
68+
{
69+
return signature;
70+
}
4971
}
5072
return nil;
5173
}
5274

5375
- (BOOL)conformsToProtocol:(Protocol *)aProtocol
5476
{
55-
return protocol_conformsToProtocol(mockedProtocol, aProtocol);
77+
for(OCProtocolProxy *protocolProxy in protocolProxies)
78+
{
79+
if([protocolProxy conformsToProtocol:aProtocol])
80+
{
81+
return YES;
82+
}
83+
}
84+
return NO;
5685
}
5786

5887
- (BOOL)respondsToSelector:(SEL)selector

Source/OCMock/OCProtocolProxy.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2005-2016 Erik Doernenburg and contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
* not use these files except in compliance with the License. You may obtain
6+
* a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
#import <Foundation/Foundation.h>
18+
19+
@interface OCProtocolProxy : NSObject
20+
21+
- (id)initWithProtocol:(Protocol *)aProtocol;
22+
23+
- (NSString *)protocolName;
24+
25+
@end

Source/OCMock/OCProtocolProxy.m

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright (c) 2005-2016 Erik Doernenburg and contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
* not use these files except in compliance with the License. You may obtain
6+
* a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
#import <objc/runtime.h>
18+
#import "NSMethodSignature+OCMAdditions.h"
19+
#import "OCProtocolProxy.h"
20+
21+
@implementation OCProtocolProxy
22+
{
23+
Protocol *mockedProtocol;
24+
}
25+
26+
#pragma mark Initialisers, description, accessors, etc.
27+
28+
- (id)initWithProtocol:(Protocol *)aProtocol
29+
{
30+
NSParameterAssert(aProtocol != nil);
31+
self = [super init];
32+
if(self)
33+
{
34+
mockedProtocol = aProtocol;
35+
}
36+
37+
return self;
38+
}
39+
40+
- (NSString *)protocolName
41+
{
42+
const char* name = protocol_getName(mockedProtocol);
43+
return [NSString stringWithUTF8String:name];
44+
}
45+
46+
#pragma mark Proxy API
47+
48+
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
49+
{
50+
struct { BOOL isRequired; BOOL isInstance; } opts[4] = { {YES, YES}, {NO, YES}, {YES, NO}, {NO, NO} };
51+
for(int i = 0; i < 4; i++)
52+
{
53+
struct objc_method_description methodDescription = protocol_getMethodDescription(mockedProtocol, aSelector, opts[i].isRequired, opts[i].isInstance);
54+
if(methodDescription.name != NULL)
55+
return [NSMethodSignature signatureWithObjCTypes:methodDescription.types];
56+
}
57+
return nil;
58+
}
59+
60+
- (BOOL)conformsToProtocol:(Protocol *)aProtocol
61+
{
62+
return protocol_conformsToProtocol(mockedProtocol, aProtocol);
63+
}
64+
65+
@end

0 commit comments

Comments
 (0)