Skip to content

Commit ceaa538

Browse files
committed
Catches references to self when not using macros.
Previous code would only catch references to self when using the OCMStub/OCMExpect macros. Now we avoid self referential retain loops if you use the `[[[foo stub] andReturn:foo] sharedInstance]` API.
1 parent 042fd19 commit ceaa538

File tree

2 files changed

+33
-14
lines changed

2 files changed

+33
-14
lines changed

Source/OCMock/OCMStubRecorder.m

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,44 +51,46 @@ - (OCMInvocationStub *)stub
5151

5252
- (id)andReturn:(id)anObject
5353
{
54-
[[self stub] addInvocationAction:[[[OCMObjectReturnValueProvider alloc] initWithValue:anObject] autorelease]];
55-
return self;
54+
Class returnValueProviderClass;
55+
if (anObject == mockObject)
56+
{
57+
returnValueProviderClass = [OCMNonRetainingObjectReturnValueProvider class];
58+
} else
59+
{
60+
returnValueProviderClass = [OCMObjectReturnValueProvider class];
61+
}
62+
[[self stub] addInvocationAction:[[[returnValueProviderClass alloc] initWithValue:anObject] autorelease]];
63+
return self;
5664
}
5765

5866
- (id)andReturnValue:(NSValue *)aValue
5967
{
6068
[[self stub] addInvocationAction:[[[OCMBoxedReturnValueProvider alloc] initWithValue:aValue] autorelease]];
61-
return self;
62-
}
63-
64-
- (id)andReturnMockObject
65-
{
66-
[[self stub] addInvocationAction:[[[OCMNonRetainingObjectReturnValueProvider alloc] initWithValue:mockObject] autorelease]];
67-
return self;
69+
return self;
6870
}
6971

7072
- (id)andThrow:(NSException *)anException
7173
{
7274
[[self stub] addInvocationAction:[[[OCMExceptionReturnValueProvider alloc] initWithValue:anException] autorelease]];
73-
return self;
75+
return self;
7476
}
7577

7678
- (id)andPost:(NSNotification *)aNotification
7779
{
7880
[[self stub] addInvocationAction:[[[OCMNotificationPoster alloc] initWithNotification:aNotification] autorelease]];
79-
return self;
81+
return self;
8082
}
8183

8284
- (id)andCall:(SEL)selector onObject:(id)anObject
8385
{
8486
[[self stub] addInvocationAction:[[[OCMIndirectReturnValueProvider alloc] initWithProvider:anObject andSelector:selector] autorelease]];
85-
return self;
87+
return self;
8688
}
8789

8890
- (id)andDo:(void (^)(NSInvocation *))aBlock
8991
{
9092
[[self stub] addInvocationAction:[[[OCMBlockCaller alloc] initWithCallBlock:aBlock] autorelease]];
91-
return self;
93+
return self;
9294
}
9395

9496
- (id)andForwardToRealObject
@@ -122,7 +124,7 @@ @implementation OCMStubRecorder (Properties)
122124
{
123125
id objValue = nil;
124126
[aValue getValue:&objValue];
125-
return (objValue == mockObject) ? [self andReturnMockObject] : [self andReturn:objValue];
127+
return [self andReturn:objValue];
126128
}
127129
else
128130
{

Source/OCMockTests/OCMockObjectTests.m

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ - (void)setUp
214214
mock = [OCMockObject mockForClass:[NSString class]];
215215
}
216216

217+
+ (void)tearDown {
218+
[super tearDown];
219+
}
220+
217221

218222
#pragma mark accepting stubbed methods / rejecting methods not stubbed
219223

@@ -574,6 +578,18 @@ - (void)testReturnsStubbedValueForProperty
574578
}
575579

576580
- (void)testReturningMockFromMethodItStubsDoesntCreateRetainCycle
581+
{
582+
@autoreleasepool {
583+
id mockWithShortLifetime = OCMClassMock([TestClassWithClassMethod class]);
584+
[[[mockWithShortLifetime stub] andReturn:@"bar"] stringValue];
585+
[[[mockWithShortLifetime stub] andReturn:mockWithShortLifetime] shared];
586+
}
587+
id singleton = [TestClassWithClassMethod shared];
588+
589+
XCTAssertEqualObjects(@"foo", [singleton stringValue], @"Should return value from real implementation (because shared is not stubbed anymore).");
590+
}
591+
592+
- (void)testReturningMockFromMethodItStubsDoesntCreateRetainCycleUsingMacros
577593
{
578594
@autoreleasepool {
579595
id mockWithShortLifetime = OCMClassMock([TestClassWithClassMethod class]);
@@ -586,6 +602,7 @@ - (void)testReturningMockFromMethodItStubsDoesntCreateRetainCycle
586602
}
587603

588604

605+
589606
#pragma mark beyond stubbing: raising exceptions, posting notifications, etc.
590607

591608
- (void)testRaisesExceptionWhenAskedTo

0 commit comments

Comments
 (0)