Skip to content

Commit 24ca2bb

Browse files
committed
Partial mocks use class created by OCClassMock
1 parent c81c481 commit 24ca2bb

File tree

2 files changed

+10
-61
lines changed

2 files changed

+10
-61
lines changed

Source/OCMock/OCPartialMockObject.m

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,10 @@ - (void)stopMocking
8686
{
8787
if(realObject != nil)
8888
{
89-
Class partialMockClass = object_getClass(realObject);
9089
OCMSetAssociatedMockForObject(nil, realObject);
9190
object_setClass(realObject, [self mockedClass]);
9291
[realObject release];
9392
realObject = nil;
94-
OCMDisposeSubclass(partialMockClass);
9593
}
9694
[super stopMocking];
9795
}
@@ -150,27 +148,30 @@ - (void)prepareObjectForInstanceMethodMocking
150148
{
151149
OCMSetAssociatedMockForObject(self, realObject);
152150

153-
/* dynamically create a subclass and set it as the class of the object */
154-
Class subclass = OCMCreateSubclass(mockedClass, realObject);
155-
object_setClass(realObject, subclass);
151+
if(!classCreatedForNewMetaClass)
152+
{
153+
classCreatedForNewMetaClass = OCMCreateSubclass(mockedClass, mockedClass);
154+
}
155+
object_setClass(realObject, classCreatedForNewMetaClass);
156156

157157
/* point forwardInvocation: of the object to the implementation in the mock */
158158
Method myForwardMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardInvocationForRealObject:));
159159
IMP myForwardIMP = method_getImplementation(myForwardMethod);
160-
class_addMethod(subclass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod));
160+
class_addMethod(classCreatedForNewMetaClass, @selector(forwardInvocation:), myForwardIMP, method_getTypeEncoding(myForwardMethod));
161161

162162
/* do the same for forwardingTargetForSelector, remember existing imp with alias selector */
163163
Method myForwardingTargetMethod = class_getInstanceMethod([self mockObjectClass], @selector(forwardingTargetForSelectorForRealObject:));
164164
IMP myForwardingTargetIMP = method_getImplementation(myForwardingTargetMethod);
165165
IMP originalForwardingTargetIMP = [mockedClass instanceMethodForSelector:@selector(forwardingTargetForSelector:)];
166-
class_addMethod(subclass, @selector(forwardingTargetForSelector:), myForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod));
167-
class_addMethod(subclass, @selector(ocmock_replaced_forwardingTargetForSelector:), originalForwardingTargetIMP, method_getTypeEncoding(myForwardingTargetMethod));
166+
const char *encoding = method_getTypeEncoding(myForwardingTargetMethod);
167+
class_addMethod(classCreatedForNewMetaClass, @selector(forwardingTargetForSelector:), myForwardingTargetIMP, encoding);
168+
class_addMethod(classCreatedForNewMetaClass, @selector(ocmock_replaced_forwardingTargetForSelector:), originalForwardingTargetIMP, encoding);
168169

169170
/* We also override the -class method to return the original class */
170171
Method myObjectClassMethod = class_getInstanceMethod([self mockObjectClass], @selector(classForRealObject));
171172
const char *objectClassTypes = method_getTypeEncoding(myObjectClassMethod);
172173
IMP myObjectClassImp = method_getImplementation(myObjectClassMethod);
173-
class_addMethod(subclass, @selector(class), myObjectClassImp, objectClassTypes);
174+
class_addMethod(classCreatedForNewMetaClass, @selector(class), myObjectClassImp, objectClassTypes);
174175

175176
/* Adding forwarder for most instance methods to allow for verify after run */
176177
NSArray *methodBlackList = @[@"class", @"forwardingTargetForSelector:", @"methodSignatureForSelector:", @"forwardInvocation:",

Source/OCMockTests/OCMockObjectPartialMocksTests.m

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -62,44 +62,6 @@ - (void)bar:(id)someArgument // maybe we should make it explicit that the arg is
6262

6363
@end
6464

65-
@interface TestClassThatObservesFoo : NSObject
66-
{
67-
@public
68-
id observedObject;
69-
}
70-
@end
71-
72-
@implementation TestClassThatObservesFoo
73-
74-
- (instancetype)initWithObject:(id)object
75-
{
76-
if((self = [super init]))
77-
observedObject = object;
78-
return self;
79-
}
80-
81-
- (void)dealloc
82-
{
83-
[self stopObserving];
84-
}
85-
86-
- (void)startObserving
87-
{
88-
[observedObject addObserver:self forKeyPath:@"foo" options:0 context:NULL];
89-
}
90-
91-
- (void)stopObserving
92-
{
93-
if(observedObject != nil)
94-
{
95-
[observedObject removeObserver:self forKeyPath:@"foo" context:NULL];
96-
observedObject = nil;
97-
}
98-
}
99-
100-
@end
101-
102-
10365
@interface TestClassThatCallsSelf : NSObject
10466
{
10567
int methodInt;
@@ -770,18 +732,4 @@ - (void)testDoesNotIncludeHintWhenStubbingIsNotGoingToHelp
770732
}
771733
}
772734

773-
- (void)testThrowsExceptionWhenAttemptingToTearDownWrongClass
774-
{
775-
TestClassWithSimpleMethod *realObject = [[TestClassWithSimpleMethod alloc] init];
776-
TestClassThatObservesFoo *observer = [[TestClassThatObservesFoo alloc] initWithObject:realObject];
777-
id mock = [OCMockObject partialMockForObject:realObject];
778-
[observer startObserving];
779-
780-
// If we invoked stopObserving here, then stopMocking would work; but we want to test the error case.
781-
XCTAssertThrowsSpecificNamed([mock stopMocking], NSException, NSInvalidArgumentException);
782-
783-
// Must reset the object here to avoid any attempt to remove the observer, which would fail.
784-
observer->observedObject = nil;
785-
}
786-
787735
@end

0 commit comments

Comments
 (0)