5

H guys, I have been trying for ages to find some good examples on how to use Kiwi testing to test delegate methods, asynchronously.

I have a manager class that defines the protocols for testing, with a pass and fail method returned in the delegate. Can anyone provide sample code on how to do this? Can I make the test class itself implement the to call the methods on the manager?

Thanks guys

Pooria Azimi
  • 8,585
  • 5
  • 30
  • 41
Doz
  • 7,009
  • 12
  • 61
  • 69

2 Answers2

6

You can do like in example

 SPEC_BEGIN(IFStackOverflowRequestSpec)

describe(@"IFStackOverflowRequestSpec", ^
{
    context(@"question request", ^
    {
        __block IFViewController *controller = nil;

         beforeEach(^
         {
             controller = [IFViewController mock];
         });

        it(@"should conform StackOverflowRequestDelegate protocol", ^
        {
             [[controller should] conformToProtocol:@protocol(StackOverflowRequestDelegate)];
        });

         it(@"should recieve receivedJSON", ^
         {
             NSString *questionsUrlString = @"http://api.stackoverflow.com/1.1/search?tagged=iphone&pagesize=20";

             IFStackOverflowRequest *request = [[IFStackOverflowRequest alloc] initWithDelegate:controller urlString:questionsUrlString];
             [[request fetchQestions] start];
             [[[controller shouldEventuallyBeforeTimingOutAfter(3)] receive] receivedJSON:any()];
         });

         it(@"should recieve fetchFailedWithError", ^
         {
             NSString *fakeUrl = @"asda";
             IFStackOverflowRequest *request = [[IFStackOverflowRequest alloc] initWithDelegate:controller urlString:fakeUrl];
             [[request fetchQestions] start];
             [[[controller shouldEventuallyBeforeTimingOutAfter(1)] receive] fetchFailedWithError:any()];
         });
    });
});

Full example can be founded on this link.

Igor
  • 4,235
  • 3
  • 34
  • 32
4

You can do what I think you're trying to achieve by creating a mock object that stands in for the delegate, and then checking that the mock object receives the delegate callbacks that you expect. So the process would look like:

  • create a mock object that conforms to the delegate protocol:

id delegateMock = [KWMock mockForProtocol:@protocol(YourProtocol)];

  • set the mock as the delegate of your manager class:

[manager setDelegate:delegateMock];

  • create an object containing the data that will be returned by your manager class:

NSString *response = @"foo";

  • set the assertion that the mock should eventually be called with the method and response object (in this case, I'm expecting to receive managerRepliedWithResponse and foo)

[[[delegateMock shouldEventually] receive] managerRepliedWithResponse:response];

  • call the method under test:

[manager performMyMethod];

The key is setting the expectation before you call the method, and using shouldEventually which delays the assertion being checked and gives the manager object time to perform the method.

There's a range of expectations you can also use that are listed on the Kiwi wiki - https://github.com/allending/Kiwi/wiki/Expectations

I've written the process up in more detail in a post on my site, albeit that it's more specifically geared-up to the situation I was dealing with.

TimD
  • 8,014
  • 2
  • 24
  • 34
  • 2
    +1 for the very subtle but very important detail! "The key is setting the expectation before you call the method" – Bach Apr 10 '13 at 20:08
  • It's been more that a year now and I am struggling with the same thing. It simply doesn't work, before/after with expectFutureValue/without. The only way I can have the damn this wait for the request to be done is by having a real value to check on somewhere. – Hugo Jul 31 '14 at 02:56