Skip to content

Commit 036739c

Browse files
committed
Partial mocks use class created by OCClassMock
1 parent 57139aa commit 036739c

File tree

2 files changed

+10
-61
lines changed

2 files changed

+10
-61
lines changed

Source/OCMock/OCPartialMockObject.m

+10-9
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

-52
Original file line numberDiff line numberDiff line change
@@ -61,44 +61,6 @@ - (void)bar:(id)someArgument // maybe we should make it explicit that the arg is
6161

6262
@end
6363

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

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

0 commit comments

Comments
 (0)