I'm trying to test the URL/path against a request is (or would be) made from a REST-client class using OCMock. The client uses RestKit (which uses AFNetworking) for the communication. Therefore my plan was to:
- Create a block which checks if a
AFHTTPRequestOperation
URL is the desired one. - Create a partial mock of the of
AFHTTPClient
. - Mock (stub) the
enqueueHTTPRequestOperation:
method with the block (of 1.). - Create a mock of
RKObjectManager
and set itsHTTPClient
property to theAFHTTPClient
partial-mock (of 2.). - Init an instance of my client-class with the mock-manager (from 4.).
- Invoke the method of this instance of which the URL is to be checked.
- Verify that
enqueueHTTPRequestOperation:
was invoked.
I'm not sure if I'm getting OCMock wrong because I couldn't find examples on mocking methods that take one or more arguments like I need to. ...never the less, this is how I tried to achieve the goal:
void (^checkBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
AFHTTPRequestOperation *requestOperation = nil;
[invocation getArgument:&requestOperation atIndex:0];
XCTAssert(requestOperation != nil);
NSString *path = requestOperation.request.URL.path;
XCTAssert([path containsString:@"/rest/user/authenticate"]);
};
AFHTTPClient *httpClientMock = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:FAServerUrl]];
OCMPartialMock(httpClientMock);
[OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg isNotNil]]) andDo:checkBlock];
RKObjectManager *objectManager = OCMClassMock([RKObjectManager class]);
[OCMStub([objectManager HTTPClient]) andReturn:httpClientMock];
FAUserClient *userClient = [[FAUserClient alloc] initWithUser:nil objectManager:objectManager];
[userClient getAccessTokenForUsername:@"testuser"
password:@"pass123"
success:^(NSString *token, NSArray *roles) {
}
failure:^(NSInteger errorCode, NSError *error) {
}];
OCMVerify([httpClientMock enqueueHTTPRequestOperation:OCMOCK_ANY]);
But on [OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg isNotNil]]) andDo:checkBlock];
I get an EXC_BAD_ACCESS (code=1).
Apparently creating the mock-stub (with OCMStub
) invokes the to be stubbed method, with the given [OCMArg isNotNil]
. I thought A: the parameter just has a declarative meaning and B: this creates a stub and does not invoke the method right away.
Any help or suggestions leading into the "right" direction would be greatly appreciated.
EDIT:
As well tried:
OCMStub([httpClientMock enqueueHTTPRequestOperation:[OCMArg checkWithBlock:^BOOL(id obj) {
AFHTTPRequestOperation *request = (AFHTTPRequestOperation *)obj;
NSString *path = request.request.URL.path;
XCTAssert([path containsString:@"/rest/user/authenticate"]);
return YES;
}]]);
...with the same "result".
Best, gabriel
Edit
Looked more closely. You are calling
OCMPartialMock(httpClientMock)
. This does not convert the object you call it on, it returns a partial mock. Capture the result in a variable.You should still make the change noted below in your
andDo:
block. You can also use the "modern" syntax for this:Original
I think the issue might be the code in the
andDo:
block.For all Objective-C methods, NSInvocation has two default arguments,
self
and_cmd
at indexes 0 and 1. Try getting the argument at index 2.You might also consider including NSInvocation+OCMAdditions which gives you
getArgumentAtIndexAsObject
. Another alternative is using[OCMArg checkWithBlock:]
in which the arg is handed to your evaluation block directly.