2

I'm new with AFNetworking framework. I've got implemented simple GET request to the server.

@implementation MyClass
…

- (void)signInWithUsername:(NSString *)username andPassword:(NSString *)password withBlock:(SignInBlock)block {
[client getPath:@"test.json" parameters:Nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    block(YES, [responseObject objectForKey:@"access_token"]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    block(NO, nil);
}];
}

block declaration:

typedef void (^SignInBlock)(BOOL success, NSString *token);

I haven't any idea how to mock this AFHTTPClient object correctly to check if block from argument (SignInBlock) has been called and with what arguments. How can I do that correctly?

Thank you in advance.

Tomasz Szulc
  • 4,217
  • 4
  • 43
  • 79
  • Checkout my answer here: http://stackoverflow.com/questions/19095322/how-to-unit-testing-afnetworking-request/19139131#19139131 – e1985 Dec 02 '13 at 17:35

2 Answers2

2

I've done it.

- (void)testTokenInBlockShouldBeNotNil {

id mockClient = [OCMockObject mockForClass:[AFHTTPClient class]];

[[[mockClient expect] andDo:^(NSInvocation *invocation) {

    void (^successBlock)(AFHTTPRequestOperation *operation, id responseObject) = nil;

    [invocation getArgument:&successBlock atIndex:4];

    successBlock(nil, @{@"access_token" : @"this_is_a_token"});

}] getPath:[OCMArg any] parameters:[OCMArg any] success:[OCMArg any] failure:[OCMArg any]] ;

RKObjectManager *manager = [[RKObjectManager alloc] init];
manager.HTTPClient = mockClient;

TokenBlock block = ^(NSString *token) {
    XCTAssertNotNil(token, @"");
};

CTFAPIConnection *connection = [[CTFAPIConnection alloc] initWithManager:manager];
_accounts = [[CTFAPIAccounts alloc] initWithConnection:connection];
id mockAccounts = [OCMockObject partialMockForObject:_accounts];
[mockAccounts signInWithUsername:[OCMArg any] andPassword:[OCMArg any] withBlock:block];
}
Tomasz Szulc
  • 4,217
  • 4
  • 43
  • 79
1

In your case you don't need to mock at all, just assert that the correct values are sent to your block:

Consider Foo:

- (void)signInWithUsername:(NSString *)username andPassword:(NSString *)password withBlock:(SignInBlock)block
{
    if ([username isEqualToString:@"Ben"])
    {
        block(YES, @"bentoken");
    }
    else
    {
        block(NO, nil);
    }
}

The test is:

- (void)testSignInWithUsername
{
    SignInBlock testYes = (SignInBlock)^(BOOL *success, NSString *token)
    {
        STAssertTrue(success, @"Expected Ben to be true");
        STAssertEqualObjects(token, @"bentoken", @"Expected the ben token");
    };
    Foo *foo = [Foo new];
    [foo signInWithUsername:@"Ben" andPassword:@"Whatever" withBlock:testYes];
}
Ben Flynn
  • 18,524
  • 20
  • 97
  • 142
  • @e1985 I was focusing on the block checking part, so in Tomasz case this would involve a network call and not really be a unit test. I don't know if there is a good unit test for the above method since `client` isn't your code (you can presume it will call the appropriate method, that it has been separately unit tested). – Ben Flynn Dec 02 '13 at 17:45
  • Thank you for help @BenFlynn. I understood how to do this earlier. Read my answer. – Tomasz Szulc Dec 02 '13 at 20:39