2

I have a following method in my app for which I need to write unit test cases.
Can anyone suggest how can I test whether the success block or error block is called.

- (IBAction)loginButtonTapped:(id)sender
{
    void (^SuccessBlock)(id, NSDictionary*) = ^(id response, NSDictionary* headers) {
        [self someMethod];
    };

    void (^ErrorBlock)(id, NSDictionary*, id) = ^(NSError* error, NSDictionary* headers, id response) {
        // some code
    };

    [ServiceClass deleteWebService:@“http://someurl"
                              data:nil
                  withSuccessBlock:SuccessBlock
                    withErrorBlock:ErrorBlock];
}
Jon Reid
  • 20,545
  • 2
  • 64
  • 95
Shubham
  • 88
  • 6

1 Answers1

1

You have to use expectations, a relatively recently introduced API. They were added to solve exactly the problem you are having right now, verifying callbacks of asynchronous methods are called.

Note that you can also set a timeout that will affect the result of the test (slow network connections for example can fire false positives, unless you are checking for slow connections of course, although there are much better ways to do that).

- (void)testThatCallbackIsCalled {

    // Given
    XCTestExpectation *expectation = [self expectationWithDescription:@"Expecting Callback"];

    // When
    void (^SuccessBlock)(id, NSDictionary*) = ^(id response, NSDictionary* headers) {

        // Then
        [self someMethod];
        [expectation fulfill]; // This tells the test that your expectation was fulfilled i.e. the callback was called.
    };

    void (^ErrorBlock)(id, NSDictionary*, id) = ^(NSError* error, NSDictionary* headers, id response) {

     // some code

    };

    [ServiceClass deleteWebService:@“http://someurl"

                                           data:nil

                               withSuccessBlock:SuccessBlock

                                 withErrorBlock:ErrorBlock];
    };

    // Here we set the timeout, play around to find what works best for your case to avoid false positives.
    [self waitForExpectationsWithTimeout:2.0 handler:nil];

}
joakim
  • 3,533
  • 2
  • 23
  • 28
  • But this will be the unit test for "deleteWebService" method. i am looking for a way where I can test "loginButtonTapped" method and check whether Success and Error block is called. – Shubham Aug 03 '15 at 12:14
  • 1
    Then use a mocking framework (e.g. OCMock, OCMockito) and verify that "deleteWebService" is called when the "loginButtonTapped" action is triggered. If you also have the "expectation" unit test for the callback, then you are covered, aren't you? – joakim Aug 03 '15 at 13:52