Skip to content

Asynchronous Unit Tests

AHHHHHH!When I created the project for RFRddMe I added Unit Tests. Every developer should do this today. They’re easy to create and Xcode does a great job getting you started. Everything is setup, you just need to write and run the tests. Really great stuff!

The only challenge for me was how to test asynchronous code? As far as I know it’s up to the developer to figure that out. That’s fine, I have a solution, but I thought I’d share it and see if anyone has an opinion about how I did it.

If you haven’t used the Unit Test Framework included with Xcode, you should. It’s a cut of SenTestingKit, and it does the trick.

It provides a couple of methods that allow you to setup and tear down a unit of tests and all you need to do is write test methods. Here’s an example test method, that does nothing.

- (void)test;
{
    STAssertTrue(true, @"test");
}

So, how in the world do you test asynchronous code? The way you write any other asynchronous code. You need a way to block until the code you’ve executed is finished.

The RFRddMe projects makes use of ASIHttpRequest, which runs in a thread. This project requires the implementation of an protocol, RFRddMeProtocol, which provides a mechanism for your application to receive results. This is all really cool because your application’s UI will remain responsive while you wait for results, but I digress.

The bottom line is we have to block while we wait on our results to return. So, here’s what I did to make this work. I created a method, I dubbed hackyRunLoopWait, that makes use of the default NSRunLoop to wait for completion of our asynchronous methods to complete. Here’s what it looks like.

// Introduced methods.
- (BOOL)hackyRunLoopWait;
{
    // Reset our _done flag.
    _done = NO;

    // Reset the _succeeded flag to NO.
    _succeeded = NO;

    // Get the current run loop.
    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];

    // Spin until the _done is YES or we've waited for 90 seconds.
    // Yep, it's a complete hack, just to get this working.
    while ((NO == _done) && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:90]]);

    // Need to deal with exiting the loop above because we timed out.
    return _succeeded;
}

Here’s how I used it to test methods on RFRddMe.

- (void)testShorten;
{
    RFRddMe* p = [[RFRddMe alloc] initWithDelegate:self];
    [p shortenUrl:@"http://iam.fahrni.ws/2011/11/15/for-posterity/"];

    STAssertTrue([self hackyRunLoopWait], @"testShorten");
    [p release];
}

Notice the STAssertTrue() statement, it contains [self hackyRunLoopWait], which blocks and waits on our shortenUrl method to complete.

Another thing to make note of is RFRddMeProtocol is implemented by the test class, see the [[RFRddMe alloc] initWithDeelgate:self]. When the request completes it will notify the shortenSucceeded method, which sets the values monitored in hackyRunLoopWait, which allows that method to return.

// RFRddMeProtocol Implementation
- (void)shortenSucceeded:(RFRddMeShortUrl*)shortUrl;
{
    _succeeded  = YES;
    _done       = YES;
}

Is this the best way? I don’t know, but it does what I need it to do, and it works as expected. If someone has a better idea I’d love to hear from you. Please, leave a comment, or send an email; rob.fahrni@gmail.com.

Categories: Development.

Tags:

Comment Feed

No Responses (yet)



Some HTML is OK

or, reply to this post via trackback.

Prices for viagra
Herbal substitute viagra
Generic nexium cialis discount
Price of viagra medicine
Purchase viagra without a prescription
Buy viagra online online href
Dexamethasone dose tinnitus intratympanic
Synthroid prescription strengths
Generic drug for diovan hct
Diovan hct 160 25mg
Yaz wrong order pills
Buy hcg clomid
Buy cipro ciprofloxacin without no prescription
Lotrisone over the counter
Levaquin 750 mg
Buy amoxicillin online rush delivery
Generic for cephalexin
Spyware mobile
Signs women cheating
Infidelity cheating
Ultram without prescription
Rx ultram er 100mg
cheater spyware
signs that my boyfriend is cheating
Tramadol online
Tramadol online
50 mg tramadol
buy pills online tramadol
Herbal excel
Male enhancement supplements extenze
how to catch a cheating boyfriend
free viagra without prescription
best price for nolvadex
lasix generic names
lidocaine buy on line
tramadol from foreign pharmacy
generic cialis
buy tramadol online
buy synthroid online
order tramadol online
buy vibramycin
buy toradol
buy lidocaine
buy celebrex
buy flagyl
lasix furosemide
canadian family pharmacy
cialis online
tramadol 100mg
nexium generic
buy nolvadex
how to catch a cheating wife
generic viagra
Canadian Family Pharmacy
buy nolvadex