Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Partial mocks now work on object reference and self. Sorry for also c…

…hanging the section headers in the same commit.

git-svn-id: http://svn.mulle-kybernetik.com/OCMock/trunk@45 12620d81-68e2-0310-ae40-e3f550779089
  • Loading branch information...
commit 4d9fa02ec3c27f12ff15a6bff087cc2e51c7d1f8 1 parent c4a5067
erik authored
6 Source/Changes.txt
View
@@ -1,6 +1,12 @@
Chronological listing of changes. If a particular SVN revision has no entry, that
check-in did not involve any code or feature changes.
+
+2009-05-26 (r45)
+
+* Partial mocks now work on object reference and self (thanks to Mike Mangino)
+
+
2009-04-24 (r43)
* Added partial mocks (calls to the original object reference cannot be mocked)
18 Source/OCClassMockObject.m
View
@@ -8,9 +8,7 @@
@implementation OCClassMockObject
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Initialisers, description, accessors, etc.
- (id)initWithClass:(Class)aClass
{
@@ -19,30 +17,18 @@ - (id)initWithClass:(Class)aClass
return self;
}
-
-//---------------------------------------------------------------------------------------
-// description override
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return [NSString stringWithFormat:@"OCMockObject[%@]", NSStringFromClass(mockedClass)];
}
-
-//---------------------------------------------------------------------------------------
-// accessors
-//---------------------------------------------------------------------------------------
-
- (Class)mockedClass
{
return mockedClass;
}
-//---------------------------------------------------------------------------------------
-// proxy api
-//---------------------------------------------------------------------------------------
+#pragma mark Proxy API
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
29 Source/OCMConstraint.m
View
@@ -6,10 +6,6 @@
#import <OCMock/OCMConstraint.h>
-//---------------------------------------------------------------------------------------
-// OCMConstraint
-//---------------------------------------------------------------------------------------
-
@implementation OCMConstraint
+ (id)constraint
@@ -48,9 +44,8 @@ + (id)constraintWithSelector:(SEL)aSelector onObject:(id)anObject withValue:(id)
@end
-//---------------------------------------------------------------------------------------
-// OCMAnyConstraint
-//---------------------------------------------------------------------------------------
+
+#pragma mark -
@implementation OCMAnyConstraint
@@ -62,9 +57,8 @@ - (BOOL)evaluate:(id)value
@end
-//---------------------------------------------------------------------------------------
-// OCMIsNilConstraint
-//---------------------------------------------------------------------------------------
+
+#pragma mark -
@implementation OCMIsNilConstraint
@@ -76,9 +70,8 @@ - (BOOL)evaluate:(id)value
@end
-//---------------------------------------------------------------------------------------
-// OCMIsNotNilConstraint
-//---------------------------------------------------------------------------------------
+
+#pragma mark -
@implementation OCMIsNotNilConstraint
@@ -90,9 +83,8 @@ - (BOOL)evaluate:(id)value
@end
-//---------------------------------------------------------------------------------------
-// OCMIsNotEqualConstraint
-//---------------------------------------------------------------------------------------
+
+#pragma mark -
@implementation OCMIsNotEqualConstraint
@@ -104,9 +96,8 @@ - (BOOL)evaluate:(id)value
@end
-//---------------------------------------------------------------------------------------
-// OCMInvocationConstraint
-//---------------------------------------------------------------------------------------
+
+#pragma mark -
@implementation OCMInvocationConstraint
15 Source/OCMObserverRecorder.m
View
@@ -12,12 +12,12 @@ @interface NSObject(HCMatcherDummy)
- (BOOL)matches:(id)item;
@end
+#pragma mark -
+
@implementation OCMObserverRecorder
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Initialisers, description, accessors, etc.
- (void)dealloc
{
@@ -26,9 +26,7 @@ - (void)dealloc
}
-//---------------------------------------------------------------------------------------
-// recording
-//---------------------------------------------------------------------------------------
+#pragma mark Recording
- (void)notificationWithName:(NSString *)name object:(id)sender
{
@@ -41,9 +39,7 @@ - (void)notificationWithName:(NSString *)name object:(id)sender userInfo:(NSDict
}
-//---------------------------------------------------------------------------------------
-// verification
-//---------------------------------------------------------------------------------------
+#pragma mark Verification
- (BOOL)matchesNotification:(NSNotification *)aNotification
{
@@ -76,5 +72,4 @@ - (BOOL)argument:(id)expectedArg matchesArgument:(id)observedArg
}
-
@end
100 Source/OCMock.xcodeproj/project.pbxproj
View
@@ -23,6 +23,9 @@
037860E20F6A3D4600A4D9A0 /* OCMPassByRefSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = 037860E10F6A3D4600A4D9A0 /* OCMPassByRefSetter.m */; };
037860E30F6A3D4600A4D9A0 /* OCMPassByRefSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 037860E00F6A3D4600A4D9A0 /* OCMPassByRefSetter.h */; };
037860E40F6A3D4600A4D9A0 /* OCMPassByRefSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = 037860E10F6A3D4600A4D9A0 /* OCMPassByRefSetter.m */; };
+ 037C13440FCC474D00257C8C /* OCPartialMockRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 037C13430FCC474D00257C8C /* OCPartialMockRecorder.m */; };
+ 037C13450FCC474D00257C8C /* OCPartialMockRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 037C13420FCC474D00257C8C /* OCPartialMockRecorder.h */; };
+ 037C13460FCC474D00257C8C /* OCPartialMockRecorder.m in Sources */ = {isa = PBXBuildFile; fileRef = 037C13430FCC474D00257C8C /* OCPartialMockRecorder.m */; };
03A2D0CB09F01D13008A1AFD /* NSInvocation+OCMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 03A2D0C909F01D13008A1AFD /* NSInvocation+OCMAdditions.h */; settings = {ATTRIBUTES = (); }; };
03A2D0CC09F01D13008A1AFD /* NSInvocation+OCMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 03A2D0CA09F01D13008A1AFD /* NSInvocation+OCMAdditions.m */; };
03BF2D4008F1C6BA00978C59 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03BF2D1B08F1C26700978C59 /* SenTestingKit.framework */; };
@@ -88,6 +91,8 @@
0378606C0F6A32F800A4D9A0 /* OCMArg.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMArg.m; sourceTree = "<group>"; };
037860E00F6A3D4600A4D9A0 /* OCMPassByRefSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMPassByRefSetter.h; sourceTree = "<group>"; };
037860E10F6A3D4600A4D9A0 /* OCMPassByRefSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMPassByRefSetter.m; sourceTree = "<group>"; };
+ 037C13420FCC474D00257C8C /* OCPartialMockRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCPartialMockRecorder.h; sourceTree = "<group>"; };
+ 037C13430FCC474D00257C8C /* OCPartialMockRecorder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCPartialMockRecorder.m; sourceTree = "<group>"; };
03A2D0C909F01D13008A1AFD /* NSInvocation+OCMAdditions.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; fileEncoding = 4; path = "NSInvocation+OCMAdditions.h"; sourceTree = "<group>"; };
03A2D0CA09F01D13008A1AFD /* NSInvocation+OCMAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSInvocation+OCMAdditions.m"; sourceTree = "<group>"; };
03A2D1F809F1533C008A1AFD /* NSInvocationOCMAdditionsTests.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = NSInvocationOCMAdditionsTests.h; sourceTree = "<group>"; };
@@ -153,6 +158,68 @@
name = Products;
sourceTree = "<group>";
};
+ 037C13470FCC475500257C8C /* Core Mocks */ = {
+ isa = PBXGroup;
+ children = (
+ 03DE1F5406DB911300E5A2A8 /* OCMockObject.h */,
+ 03DE1F5506DB911300E5A2A8 /* OCMockObject.m */,
+ 0338A99607BE7C100066DE8A /* OCClassMockObject.h */,
+ 0338A99707BE7C100066DE8A /* OCClassMockObject.m */,
+ 0338A9EE07BE83B50066DE8A /* OCProtocolMockObject.h */,
+ 0338A9EF07BE83B50066DE8A /* OCProtocolMockObject.m */,
+ 03DE1F5606DB911300E5A2A8 /* OCMockRecorder.h */,
+ 03DE1F5706DB911300E5A2A8 /* OCMockRecorder.m */,
+ );
+ name = "Core Mocks";
+ sourceTree = "<group>";
+ };
+ 037C13480FCC478500257C8C /* Partial Mocks */ = {
+ isa = PBXGroup;
+ children = (
+ 03D8822D0FA151E10087D071 /* OCPartialMockObject.h */,
+ 03D8822E0FA151E20087D071 /* OCPartialMockObject.m */,
+ 037C13420FCC474D00257C8C /* OCPartialMockRecorder.h */,
+ 037C13430FCC474D00257C8C /* OCPartialMockRecorder.m */,
+ );
+ name = "Partial Mocks";
+ sourceTree = "<group>";
+ };
+ 037C13490FCC479D00257C8C /* Observer Mocks */ = {
+ isa = PBXGroup;
+ children = (
+ 03D8805E0F8C81DE0087D071 /* OCObserverMockObject.h */,
+ 03D8805F0F8C81DE0087D071 /* OCObserverMockObject.m */,
+ 03D881070F8DB0BB0087D071 /* OCMObserverRecorder.h */,
+ 03D8815A0F8DB37B0087D071 /* OCMObserverRecorder.m */,
+ );
+ name = "Observer Mocks";
+ sourceTree = "<group>";
+ };
+ 037C134A0FCC47B500257C8C /* Argument Handling */ = {
+ isa = PBXGroup;
+ children = (
+ 0378606B0F6A32F800A4D9A0 /* OCMArg.h */,
+ 0378606C0F6A32F800A4D9A0 /* OCMArg.m */,
+ 0343133B0CCA771800A2E080 /* OCMConstraint.h */,
+ 0343133C0CCA771800A2E080 /* OCMConstraint.m */,
+ 037860E00F6A3D4600A4D9A0 /* OCMPassByRefSetter.h */,
+ 037860E10F6A3D4600A4D9A0 /* OCMPassByRefSetter.m */,
+ );
+ name = "Argument Handling";
+ sourceTree = "<group>";
+ };
+ 037C134B0FCC47CA00257C8C /* Foundation Additions */ = {
+ isa = PBXGroup;
+ children = (
+ 03A2D0C909F01D13008A1AFD /* NSInvocation+OCMAdditions.h */,
+ 03A2D0CA09F01D13008A1AFD /* NSInvocation+OCMAdditions.m */,
+ 03D880D30F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.h */,
+ 03D880D40F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.m */,
+ 0338AA1007BE866F0066DE8A /* NSMethodSignature+Private.h */,
+ );
+ name = "Foundation Additions";
+ sourceTree = "<group>";
+ };
03DE1F5D06DB911C00E5A2A8 /* Tests */ = {
isa = PBXGroup;
children = (
@@ -217,31 +284,11 @@
08FB77AEFE84172EC02AAC07 /* Implementation */ = {
isa = PBXGroup;
children = (
- 03DE1F5406DB911300E5A2A8 /* OCMockObject.h */,
- 03DE1F5506DB911300E5A2A8 /* OCMockObject.m */,
- 0338A99607BE7C100066DE8A /* OCClassMockObject.h */,
- 0338A99707BE7C100066DE8A /* OCClassMockObject.m */,
- 0338A9EE07BE83B50066DE8A /* OCProtocolMockObject.h */,
- 0338A9EF07BE83B50066DE8A /* OCProtocolMockObject.m */,
- 03D8822D0FA151E10087D071 /* OCPartialMockObject.h */,
- 03D8822E0FA151E20087D071 /* OCPartialMockObject.m */,
- 03DE1F5606DB911300E5A2A8 /* OCMockRecorder.h */,
- 03DE1F5706DB911300E5A2A8 /* OCMockRecorder.m */,
- 03D8805E0F8C81DE0087D071 /* OCObserverMockObject.h */,
- 03D8805F0F8C81DE0087D071 /* OCObserverMockObject.m */,
- 03D881070F8DB0BB0087D071 /* OCMObserverRecorder.h */,
- 03D8815A0F8DB37B0087D071 /* OCMObserverRecorder.m */,
- 0378606B0F6A32F800A4D9A0 /* OCMArg.h */,
- 0378606C0F6A32F800A4D9A0 /* OCMArg.m */,
- 0343133B0CCA771800A2E080 /* OCMConstraint.h */,
- 0343133C0CCA771800A2E080 /* OCMConstraint.m */,
- 037860E00F6A3D4600A4D9A0 /* OCMPassByRefSetter.h */,
- 037860E10F6A3D4600A4D9A0 /* OCMPassByRefSetter.m */,
- 03A2D0C909F01D13008A1AFD /* NSInvocation+OCMAdditions.h */,
- 03A2D0CA09F01D13008A1AFD /* NSInvocation+OCMAdditions.m */,
- 03D880D30F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.h */,
- 03D880D40F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.m */,
- 0338AA1007BE866F0066DE8A /* NSMethodSignature+Private.h */,
+ 037C13470FCC475500257C8C /* Core Mocks */,
+ 037C13480FCC478500257C8C /* Partial Mocks */,
+ 037C13490FCC479D00257C8C /* Observer Mocks */,
+ 037C134A0FCC47B500257C8C /* Argument Handling */,
+ 037C134B0FCC47CA00257C8C /* Foundation Additions */,
);
name = Implementation;
sourceTree = "<group>";
@@ -293,6 +340,7 @@
03D880D50F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.h in Headers */,
03D881090F8DB0BB0087D071 /* OCMObserverRecorder.h in Headers */,
03D8822F0FA151E20087D071 /* OCPartialMockObject.h in Headers */,
+ 037C13450FCC474D00257C8C /* OCPartialMockRecorder.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -438,6 +486,7 @@
03D880D70F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.m in Sources */,
03D8815C0F8DB37B0087D071 /* OCMObserverRecorder.m in Sources */,
03D882310FA151E20087D071 /* OCPartialMockObject.m in Sources */,
+ 037C13440FCC474D00257C8C /* OCPartialMockRecorder.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -457,6 +506,7 @@
03D880D60F8DA4750087D071 /* NSNotificationCenter+OCMAdditions.m in Sources */,
03D8815B0F8DB37B0087D071 /* OCMObserverRecorder.m in Sources */,
03D882300FA151E20087D071 /* OCPartialMockObject.m in Sources */,
+ 037C13460FCC474D00257C8C /* OCPartialMockRecorder.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
3  Source/OCMockObject.h
View
@@ -29,4 +29,7 @@
- (void)verify;
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation;
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation;
+
@end
51 Source/OCMockObject.m
View
@@ -13,16 +13,16 @@
@interface OCMockObject(Private)
+ (id)_makeNice:(OCMockObject *)mock;
-- (BOOL)_handleInvocation:(NSInvocation *)anInvocation;
-- (void)_handleUnRecordedInvocation:(NSInvocation *)anInvocation;
- (NSString *)_recorderDescriptions:(BOOL)onlyExpectations;
@end
+#pragma mark -
+
+
+
@implementation OCMockObject
-//---------------------------------------------------------------------------------------
-// factory methods
-//---------------------------------------------------------------------------------------
+#pragma mark Factory methods
+ (id)mockForClass:(Class)aClass
{
@@ -64,9 +64,14 @@ + (id)observerMock
}
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
++ (id)recorderForMock:(OCMockObject *)mock
+{
+ return [[[OCMockRecorder alloc] initWithSignatureResolver:mock] autorelease];
+}
+
+
+
+#pragma mark Initialisers, description, accessors, etc.
- (id)init
{
@@ -84,23 +89,18 @@ - (void)dealloc
[super dealloc];
}
-//---------------------------------------------------------------------------------------
-// description override
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return @"OCMockObject";
}
-//---------------------------------------------------------------------------------------
-// public api
-//---------------------------------------------------------------------------------------
+
+#pragma mark Public API
- (id)stub
{
- OCMockRecorder *recorder = [[[OCMockRecorder alloc] initWithSignatureResolver:self] autorelease];
+ OCMockRecorder *recorder = [[self class] recorderForMock:self];
[recorders addObject:recorder];
return recorder;
}
@@ -133,22 +133,16 @@ - (void)verify
}
-//---------------------------------------------------------------------------------------
-// proxy api
-//---------------------------------------------------------------------------------------
+
+#pragma mark Handling invocations
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
- if([self _handleInvocation:anInvocation] == NO)
- [self _handleUnRecordedInvocation:anInvocation];
+ if([self handleInvocation:anInvocation] == NO)
+ [self handleUnRecordedInvocation:anInvocation];
}
-
-//---------------------------------------------------------------------------------------
-// internal methods
-//---------------------------------------------------------------------------------------
-
-- (BOOL)_handleInvocation:(NSInvocation *)anInvocation
+- (BOOL)handleInvocation:(NSInvocation *)anInvocation
{
OCMockRecorder *recorder = nil;
int i;
@@ -173,7 +167,7 @@ - (BOOL)_handleInvocation:(NSInvocation *)anInvocation
return YES;
}
-- (void)_handleUnRecordedInvocation:(NSInvocation *)anInvocation
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
{
if(isNice == NO)
{
@@ -185,7 +179,6 @@ - (void)_handleUnRecordedInvocation:(NSInvocation *)anInvocation
}
}
-
- (NSString *)_recorderDescriptions:(BOOL)onlyExpectations
{
NSMutableString *outputString = [NSMutableString string];
49 Source/OCMockObjectTests.m
View
@@ -439,32 +439,47 @@ - (void)testRaisesAnExceptionWenAnExpectedMethodIsNotCalledOnNiceProtocolMock
- (void)testStubsMethodsOnPartialMock
{
- mock = [OCMockObject partialMockForObject:[NSString stringWithString:@"hello"]];
- [[[mock stub] andReturn:@"hi"] uppercaseString];
- STAssertEqualObjects(@"hi", [mock uppercaseString], @"Should have returned stubbed value");
+ TestClassThatCallsSelf *foo = [[[TestClassThatCallsSelf alloc] init] autorelease];
+ mock = [OCMockObject partialMockForObject:foo];
+ [[[mock stub] andReturn:@"hi"] method1];
+ STAssertEqualObjects(@"hi", [mock method1], @"Should have returned stubbed value");
}
+//- (void)testStubsMethodsOnPartialMockForClassCluster
+//{
+// mock = [OCMockObject partialMockForObject:[NSString stringWithString:@"hello"]];
+// [[[mock stub] andReturn:@"hi"] uppercaseString];
+// STAssertEqualObjects(@"hi", [mock uppercaseString], @"Should have returned stubbed value");
+//}
+
- (void)testForwardsUnstubbedMethodsCallsToRealObjectOnPartialMock
{
- mock = [OCMockObject partialMockForObject:[NSString stringWithString:@"hello2"]];
- STAssertEqualObjects(@"HELLO2", [mock uppercaseString], @"Should have returned value from real object.");
+ TestClassThatCallsSelf *foo = [[[TestClassThatCallsSelf alloc] init] autorelease];
+ mock = [OCMockObject partialMockForObject:foo];
+ STAssertEqualObjects(@"Foo", [mock method2], @"Should have returned value from real object.");
}
-//- (void)testStubsMethodOnRealObjectReference
+//- (void)testForwardsUnstubbedMethodsCallsToRealObjectOnPartialMockForClassCluster
//{
-// NSString *realObject = [NSString stringWithString:@"hello3"];
-// mock = [OCMockObject partialMockForObject:realObject];
-// [[[mock stub] andReturn:@"hi"] uppercaseString];
-// STAssertEqualObjects(@"hi", [realObject uppercaseString], @"Should have stubbed method.");
+// mock = [OCMockObject partialMockForObject:[NSString stringWithString:@"hello2"]];
+// STAssertEqualObjects(@"HELLO2", [mock uppercaseString], @"Should have returned value from real object.");
//}
-//- (void)testCallsToSelfInRealObjectAreShadowedByPartialMock
-//{
-// TestClassThatCallsSelf *foo = [[[TestClassThatCallsSelf alloc] init] autorelease];
-// mock = [OCMockObject partialMockForObject:foo];
-// [[[mock stub] andReturn:@"FooFoo"] method2];
-// STAssertEqualObjects(@"FooFoo", [mock method1], @"Should have called through to stubbed method.");
-//}
+- (void)testStubsMethodOnRealObjectReference
+{
+ TestClassThatCallsSelf *realObject = [[[TestClassThatCallsSelf alloc] init] autorelease];
+ mock = [OCMockObject partialMockForObject:realObject];
+ [[[mock stub] andReturn:@"FooFoo"] method1];
+ STAssertEqualObjects(@"FooFoo", [realObject method1], @"Should have stubbed method.");
+}
+
+- (void)testCallsToSelfInRealObjectAreShadowedByPartialMock
+{
+ TestClassThatCallsSelf *foo = [[[TestClassThatCallsSelf alloc] init] autorelease];
+ mock = [OCMockObject partialMockForObject:foo];
+ [[[mock stub] andReturn:@"FooFoo"] method2];
+ STAssertEqualObjects(@"FooFoo", [mock method1], @"Should have called through to stubbed method.");
+}
// --------------------------------------------------------------------------------------
41 Source/OCMockRecorder.m
View
@@ -14,12 +14,12 @@ @interface NSObject(HCMatcherDummy)
- (BOOL)matches:(id)item;
@end
+#pragma mark -
+
@implementation OCMockRecorder
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Initialisers, description, accessors, etc.
- (id)initWithSignatureResolver:(id)anObject
{
@@ -27,7 +27,6 @@ - (id)initWithSignatureResolver:(id)anObject
return self;
}
-
- (void)dealloc
{
[recordedInvocation release];
@@ -35,20 +34,19 @@ - (void)dealloc
[super dealloc];
}
-
-//---------------------------------------------------------------------------------------
-// description
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return [recordedInvocation invocationDescription];
}
+- (void)releaseInvocation
+{
+ [recordedInvocation release];
+ recordedInvocation = nil;
+}
-//---------------------------------------------------------------------------------------
-// recording
-//---------------------------------------------------------------------------------------
+
+#pragma mark Setting up behaviour
- (id)andReturn:(id)anObject
{
@@ -73,12 +71,15 @@ - (id)andThrow:(NSException *)anException
return self;
}
+
+
+#pragma mark Proxy API
+
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [signatureResolver methodSignatureForSelector:aSelector];
}
-
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if(recordedInvocation != nil)
@@ -89,9 +90,8 @@ - (void)forwardInvocation:(NSInvocation *)anInvocation
}
-//---------------------------------------------------------------------------------------
-// verification and return values
-//---------------------------------------------------------------------------------------
+
+#pragma mark Verification and return values
- (id)_extractArgument: (NSInvocation*)anInvocation atIndex:(int)index
{
@@ -290,14 +290,5 @@ - (void)setUpReturnValue:(NSInvocation *)anInvocation
}
-//---------------------------------------------------------------------------------------
-// House-keeping
-//---------------------------------------------------------------------------------------
-
-- (void)releaseInvocation
-{
- [recordedInvocation release];
- recordedInvocation = nil;
-}
@end
19 Source/OCObserverMockObject.m
View
@@ -9,9 +9,7 @@
@implementation OCObserverMockObject
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Initialisers, description, accessors, etc.
- (id)init
{
@@ -26,20 +24,14 @@ - (void)dealloc
[super dealloc];
}
-
-//---------------------------------------------------------------------------------------
-// description override
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return @"OCMockObserver";
}
-//---------------------------------------------------------------------------------------
-// public api
-//---------------------------------------------------------------------------------------
+
+#pragma mark Public API
- (id)expect
{
@@ -63,9 +55,8 @@ - (void)verify
}
-//---------------------------------------------------------------------------------------
-// receiving notifications
-//---------------------------------------------------------------------------------------
+
+#pragma mark Receiving notifications
- (void)handleNotification:(NSNotification *)aNotification
{
5 Source/OCPartialMockObject.h
View
@@ -13,4 +13,9 @@
- (id)initWithObject:(NSObject *)anObject;
+- (NSObject *)realObject;
+
+- (void)setupSubclassForObject:(id)anObject;
+- (void)setupForwarderForSelector:(SEL)selector;
+
@end
112 Source/OCPartialMockObject.m
View
@@ -3,46 +3,130 @@
// Copyright (c) 2009 by Mulle Kybernetik. See License file for details.
//---------------------------------------------------------------------------------------
+#import <objc/runtime.h>
+#import <objc/objc.h>
+#import <objc/objc-runtime.h>
+#import <objc/objc-api.h>
+#import <objc/objc-class.h>
+#import "OCPartialMockRecorder.h"
#import "OCPartialMockObject.h"
-@interface OCMockObject(Private)
-+ (id)_makeNice:(OCMockObject *)mock;
-- (BOOL)_handleRecordedInvocations:(NSInvocation *)anInvocation;
-- (NSString *)_recorderDescriptions:(BOOL)onlyExpectations;
-@end
@implementation OCPartialMockObject
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Factory methods
+
++ (id)recorderForMock:(OCMockObject *)mock
+{
+ return [[[OCPartialMockRecorder alloc] initWithSignatureResolver:mock] autorelease];
+}
+
+
+
+#pragma mark Mock table
+
+static NSMutableDictionary *mockTable;
+
++ (void)initialize
+{
+ if(self == [OCPartialMockObject class])
+ mockTable = [[NSMutableDictionary alloc] init];
+}
+
++ (void)rememberPartialMock:(OCPartialMockObject *)mock forObject:(id)anObject
+{
+ [mockTable setObject:mock forKey:[NSValue valueWithNonretainedObject:anObject]];
+}
+
++ (void)forgetPartialMockForObject:(id)anObject
+{
+ [mockTable removeObjectForKey:[NSValue valueWithNonretainedObject:anObject]];
+}
+
++ (OCPartialMockObject *)partialMockForObject:(id)anObject
+{
+ OCPartialMockObject *mock = [mockTable objectForKey:[NSValue valueWithNonretainedObject:anObject]];
+ if(mock == nil)
+ [NSException raise:NSInternalInconsistencyException format:@"No partial mock for object %p", anObject];
+ return mock;
+}
+
+
+
+#pragma mark Initialisers, description, accessors, etc.
- (id)initWithObject:(NSObject *)anObject
{
[super initWithClass:[anObject class]];
realObject = [anObject retain];
+ [[self class] rememberPartialMock:self forObject:anObject];
+ [self setupSubclassForObject:realObject];
return self;
}
- (void)dealloc
{
+ object_setClass(realObject, [self mockedClass]);
[realObject release];
+ [[self class] forgetPartialMockForObject:realObject];
[super dealloc];
}
-
-//---------------------------------------------------------------------------------------
-// overrides
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return [NSString stringWithFormat:@"OCPartialMockObject[%@]", NSStringFromClass(mockedClass)];
}
-- (void)_handleUnRecordedInvocation:(NSInvocation *)anInvocation
+- (NSObject *)realObject
+{
+ return realObject;
+}
+
+
+
+#pragma mark Subclass management
+
+- (void)setupSubclassForObject:(id)anObject
+{
+ Class realClass = [anObject class];
+ const char *className = [[NSString stringWithFormat:@"%@-%p", realClass, anObject] cString];
+ NSLog(@"Creating class named %s", className);
+ Class subclass = objc_allocateClassPair(realClass, className, 0);
+ objc_registerClassPair(subclass);
+ object_setClass(anObject, subclass);
+
+ Method forwardInvocationMethod = class_getInstanceMethod([self class], @selector(forwardInvocationForRealObject:));
+ IMP forwardInvocationImp = method_getImplementation(forwardInvocationMethod);
+ const char *forwardInvocationTypes = method_getTypeEncoding(forwardInvocationMethod);
+ class_addMethod(subclass, @selector(forwardInvocation:), forwardInvocationImp, forwardInvocationTypes);
+}
+
+- (void)setupForwarderForSelector:(SEL)selector
+{
+ Class subclass = [[self realObject] class];
+ Method originalMethod = class_getInstanceMethod(subclass, selector);
+ IMP forwarderImp = [subclass instanceMethodForSelector:@selector(aMethodThatMustNotExist)];
+ class_addMethod(subclass, method_getName(originalMethod), forwarderImp, method_getTypeEncoding(originalMethod));
+}
+
+- (void)forwardInvocationForRealObject:(NSInvocation *)anInvocation
+{
+ // in here "self" is a reference to the real object, not the mock
+ OCPartialMockObject *mock = [OCPartialMockObject partialMockForObject:self];
+ if([mock handleInvocation:anInvocation] == NO)
+ [NSException raise:NSInternalInconsistencyException format:@"Ended up in subclass forwarder for %@ with unstubbed method %@",
+ [self class], NSStringFromSelector([anInvocation selector])];
+ NSLog(@"#&*%^*#%^ self = %@, mock = %@", [self class], mock);
+}
+
+
+
+#pragma mark Invocation handling
+
+- (void)handleUnRecordedInvocation:(NSInvocation *)anInvocation
{
[anInvocation invokeWithTarget:realObject];
}
+
@end
13 Source/OCPartialMockRecorder.h
View
@@ -0,0 +1,13 @@
+//---------------------------------------------------------------------------------------
+// $Id: OCPartialMockRecorder.h $
+// Copyright (c) 2009 by Mulle Kybernetik. See License file for details.
+//---------------------------------------------------------------------------------------
+
+#import "OCMockRecorder.h"
+
+
+@interface OCPartialMockRecorder : OCMockRecorder
+{
+}
+
+@end
19 Source/OCPartialMockRecorder.m
View
@@ -0,0 +1,19 @@
+//---------------------------------------------------------------------------------------
+// $Id: OCPartialMockRecorder.m $
+// Copyright (c) 2009 by Mulle Kybernetik. See License file for details.
+//---------------------------------------------------------------------------------------
+
+#import "OCPartialMockObject.h"
+#import "OCPartialMockRecorder.h"
+
+
+@implementation OCPartialMockRecorder
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation
+{
+ [super forwardInvocation:anInvocation];
+ // not as clean as I'd wish...
+ [(OCPartialMockObject *)signatureResolver setupForwarderForSelector:[anInvocation selector]];
+}
+
+@end
14 Source/OCProtocolMockObject.m
View
@@ -10,9 +10,7 @@
@implementation OCProtocolMockObject
-//---------------------------------------------------------------------------------------
-// init and dealloc
-//---------------------------------------------------------------------------------------
+#pragma mark Initialisers, description, accessors, etc.
- (id)initWithProtocol:(Protocol *)aProtocol
{
@@ -21,20 +19,14 @@ - (id)initWithProtocol:(Protocol *)aProtocol
return self;
}
-
-//---------------------------------------------------------------------------------------
-// description override
-//---------------------------------------------------------------------------------------
-
- (NSString *)description
{
return [NSString stringWithFormat:@"OCMockObject[%s]", [mockedProtocol name]];
}
-//---------------------------------------------------------------------------------------
-// proxy api
-//---------------------------------------------------------------------------------------
+
+#pragma mark Proxy API
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
Please sign in to comment.
Something went wrong with that request. Please try again.