kakyo
kakyo

Reputation: 11600

C/ObjC: How to unit-test blocks?

According to this Stackoverflow post: Selectors or Blocks for callbacks in an Objective-C library ,

blocks seem to be the future of ObjC. However, much like anonymous functions, blocks feel more like "drafting" an implementation. Also, due to its "embedded" nature, I fear that overusing them will break modularity in the sense of unit-testing or "testable" OOP.

I couldn't find much guideline on how to test blocks and how to coordinate tests for blocks and regular methods. Are there good resources for this topic?

Upvotes: 1

Views: 1897

Answers (3)

long Tan
long Tan

Reputation: 11

- (void)testWaitForBlock {
    [target selectorWithInlineBlock:^(id obj) {

        // assertions

        BlockFinished();
    }];
   //use this to keep runloop is alive ,you can do anything.
   NSDate * date = [NSDate dateWithTimeIntervalSinceNow:10];
    [[NSRunLoop currentRunLoop]runUntilDate:date];
}

Upvotes: 0

Raphael Oliveira
Raphael Oliveira

Reputation: 7841

I created 3 macros that wait for the block to be executed in a unit test so the assertions can be made inside the block.

#define TestNeedsToWaitForBlock() __block BOOL blockFinished = NO
#define BlockFinished() blockFinished = YES
#define WaitForBlock() while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) && !blockFinished)

Example:

- (void)testWaitForBlock {
    TestNeedsToWaitForBlock();

    [target selectorWithInlineBlock:^(id obj) {

        // assertions

        BlockFinished();
    }];

    WaitForBlock();
}

Upvotes: 17

Chris
Chris

Reputation: 56

Not sure if you've already tried it, but I use Kiwi for unit testing my iOS applications. Its not amazingly documented but it can be used for testing blocks.

https://github.com/allending/Kiwi

Take a look at the 'capturing arguments' under 'mocks and stubs' on their wiki. You can use this to capture a block thats being passed. This is really useful for code thats asynchronous - you can call the method you want to test, capture some completion block and then immediately execute the block synchronously, making your asynchronous code effectively synchronous.

In reference to blocks feeling like drafting an implementation - they don't have to be like that. I define blocks as a would a method, not inline. In fact I often write a method to return the block, making the code clean and easily testable.

Not sure if thats what you were looking for.

Upvotes: 4

Related Questions