How to stub a class method in OCMock?

前端 未结 5 1754
谎友^
谎友^ 2020-12-29 03:04

I often find in my iPhone Objective-C unit tests that I want stub out a class method, e.g. NSUrlConnection\'s +sendSynchronousRequest:returningResponse:error: method.

<
5条回答
  •  醉梦人生
    2020-12-29 03:51

    Update for OCMock 3

    OCMock has modernized its syntax for supporting class method stubbing:

    id classMock = OCMClassMock([SomeClass class]);
    OCMStub(ClassMethod([classMock aMethod])).andReturn(aValue);
    

    Update

    OCMock now supports class method stubbing out of the box. The OP's code should now work as posted. If there is an instance method with the same name as the class method, the syntax is:

    [[[[mock stub] classMethod] andReturn:aValue] aMethod]
    

    See OCMock's Features.

    Original Answer

    Sample code following Barry Wark's answer.

    The fake class, just stubbing connectionWithRequest:delegate:

    @interface FakeNSURLConnection : NSURLConnection
    + (id)sharedInstance;
    + (void)setSharedInstance:(id)sharedInstance;
    + (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
    - (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
    @end
    @implementation FakeNSURLConnection
    static id _sharedInstance;
    + (id)sharedInstance { if (!_sharedInstance) { _sharedInstance = [self init]; } return _sharedInstance; }
    + (void)setSharedInstance:(id)sharedInstance { _sharedInstance = sharedInstance; }
    + (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate {
        return [FakeNSURLConnection.sharedInstance connectionWithRequest:request delegate:delegate];
    }
    - (NSURLConnection *)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate { return nil; }
    @end
    

    Switching to and from the mock:

    {
        ...
        // Create the mock and swap it in
        id nsurlConnectionMock = [OCMockObject niceMockForClass:FakeNSURLConnection.class];
        [FakeNSURLConnection setSharedInstance:nsurlConnectionMock];
        Method urlOriginalMethod = class_getClassMethod(NSURLConnection.class, @selector(connectionWithRequest:delegate:));
        Method urlNewMethod = class_getClassMethod(FakeNSURLConnection.class, @selector(connectionWithRequest:delegate:));
        method_exchangeImplementations(urlOriginalMethod, urlNewMethod);
    
        [[nsurlConnectionMock expect] connectionWithRequest:OCMOCK_ANY delegate:OCMOCK_ANY];
    
        ...
        // Make the call which will do the connectionWithRequest:delegate call
        ...
    
        // Verify
        [nsurlConnectionMock verify];
    
        // Unmock
        method_exchangeImplementations(urlNewMethod, urlOriginalMethod);
    }
    

提交回复
热议问题