How can I get OCMock under ARC to stop nilling an NSProxy subclass set using a weak property?

前端 未结 3 1204
夕颜
夕颜 2020-12-31 12:01

Under ARC, I have an object, Child that has a weak property, parent. I\'m trying to write some tests for Child

3条回答
  •  悲哀的现实
    2020-12-31 12:33

    I found a different solution than a conditional macro since I was testing code that I could not change the code for.

    I wrote a simple class that extends NSObject, not NSProxy, that forwards all selector invocations on to the OCMockProxy.

    CCWeakMockProxy.h:

    #import 
    
    /**
     * This class is a hack around the fact that ARC weak references are immediately nil'd if the referent is an NSProxy
     * See: http://stackoverflow.com/questions/9104544/how-can-i-get-ocmock-under-arc-to-stop-nilling-an-nsproxy-subclass-set-using-a-w
     */
    @interface CCWeakMockProxy : NSObject
    
    @property (strong, nonatomic) id mock;
    
    - (id)initWithMock:(id)mockObj;
    
    + (id)mockForClass:(Class)aClass;
    + (id)mockForProtocol:(Protocol *)aProtocol;
    + (id)niceMockForClass:(Class)aClass;
    + (id)niceMockForProtocol:(Protocol *)aProtocol;
    + (id)observerMock;
    + (id)partialMockForObject:(NSObject *)anObject;
    
    @end
    

    CCWeakMockProxy.m:

    #import "CCWeakMockProxy.h"
    #import 
    
    
    #pragma mark Implementation
    @implementation CCWeakMockProxy
    
    #pragma mark Properties
    @synthesize mock;
    
    #pragma mark Memory Management
    - (id)initWithMock:(id)mockObj {
        if (self = [super init]) {
            self.mock = mockObj;
        }
        return self;
    }
    
    #pragma mark NSObject
    - (id)forwardingTargetForSelector:(SEL)aSelector {
        return self.mock;
    }
    
    - (BOOL)respondsToSelector:(SEL)aSelector {
        return [self.mock respondsToSelector:aSelector];
    }
    
    #pragma mark Public Methods
    + (id)mockForClass:(Class)aClass {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject mockForClass:aClass]];
    }
    
    + (id)mockForProtocol:(Protocol *)aProtocol {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject mockForProtocol:aProtocol]];
    }
    
    + (id)niceMockForClass:(Class)aClass {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject niceMockForClass:aClass]];
    }
    
    + (id)niceMockForProtocol:(Protocol *)aProtocol {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject niceMockForProtocol:aProtocol]];
    }
    
    + (id)observerMock {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject observerMock]];
    }
    
    + (id)partialMockForObject:(NSObject *)anObject {
        return [[CCWeakMockProxy alloc] initWithMock:[OCMockObject partialMockForObject:anObject]];
    }
    
    @end
    

    Just use the resulting object as you would a regular OCMockObject!

提交回复
热议问题