1

I'm using Kiwi to write the tests for my app.

I wrote tests to test against my API. I was guided by this example in the documentation for testing asynchronous calls: https://github.com/allending/Kiwi/wiki/Asynchronous-Testing

My tests are long, so I made a simplified version of my issue:

describe(@"My Class Name", ^{
   context(@"populate", ^{
      it(@"download the content", ^{

          __block NSString *testResponseObject = nil;
          __block NSError *testError = nil;
          MyClient *apiClient = [MyClient sharedClient];

          NSMutableURLRequest *request = [apiClient requestWithMethod:@"DELETE" path:@"my/path" parameters:nil];
          AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

          [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
              testResponseObject = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
          } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
              testError = error;
          }];

          [apiClient enqueueHTTPRequestOperation:operation];

          [[expectFutureValue(testResponseObject) shouldEventuallyBeforeTimingOutAfter(100)] equal:@"Expected Content"];
          [[expectFutureValue(testError) shouldEventuallyBeforeTimingOutAfter(100)] shouldBeNil];
      });
   });
});

The thing is that if everything works as expected & the operation succeeds the failure block never gets called & instead of nil for NSError I get KWAsyncVerifier.

I'm guessing that's because Kiwi waits for the block where testError is referenced to be executed which never happens & that's why I have KWAsyncVerifier stuck into testError instead of nil.

Is there any alternative how to test this out?

Kex
  • 776
  • 10
  • 22

1 Answers1

2

My first recommendation is that you should not test your libraries. From what I read in your example, you are basically checking that AFHTTPRequestOperation is working as documented, but that’s not your responsability to test. You should test that you invoke AFNetworking correctly, and that given an responseObject or an error, your code behaves as you expect.

Anyway, about what you are seeing, you have two “shoulds” in the same line: shouldEventually and shouldBeNil; they use to have beNil matcher, which is unavailable in 2.1, and I think they are bringing back. You can find the discussion in https://github.com/allending/Kiwi/issues/293

Maybe you can try the following to make sure that the failure branch is not taken:

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
  testResponseObject = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
  // This will fail if we ever reach this branch
  [error shouldBeNil];
}];

[apiClient enqueueHTTPRequestOperation:operation];

[[expectFutureValue(testResponseObject) shouldEventuallyBeforeTimingOutAfter(100)] equal:@"Expected Content"];

The shouldEventuallyBeforeTimingOutAfter will keep the test case “alive” waiting to check the response, but if you ever go through the failure branch, the other expectation will fail (and also the one in response will fail after 100 seconds). Hope it helps.

yonosoytu
  • 3,319
  • 1
  • 17
  • 23
  • @yonosoyty indeed, I used an another should for matching because I saw that beNil is not available anymore & I guessed that they merged shouldBeNil with beNil. Anyhow my idea is to write tests for the communication with the API, in case they check with one run if they made some changes .. – Kex Jun 22 '13 at 17:14
  • I think you could just remove the expectation on testError. Due to the structure of your test, you can assume that testError will always be nil as long as testResponseObject has the expected value. The only way both variables could be non-nil is if *both* your success and failure blocks are called; I would say it's reasonable to assume this would never happen. – Mike Mertsock Jun 22 '13 at 17:19
  • I’m with @esker, testing for the successful branch should be enough, but look at my update, if you really need to check for the failure branch. – yonosoytu Jun 22 '13 at 18:03