根据此Stackoverflow帖子:Selectors or Blocks for callbacks in an Objective-C library,
块似乎是ObjC的未来。然而,就像匿名函数一样,块感觉更像是“起草”一个实现。此外,由于其“嵌入式”性质,我担心过度使用它们会破坏单元测试或“可测试”OOP意义上的模块化。
我找不到关于如何测试块以及如何协调块和常规方法的测试的指南。这个话题有很好的资源吗?
答案 0 :(得分:16)
我创建了3个等待块在单元测试中执行的宏,因此断言可以在块内完成。
#define TestNeedsToWaitForBlock() __block BOOL blockFinished = NO
#define BlockFinished() blockFinished = YES
#define WaitForBlock() while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true) && !blockFinished)
示例:
- (void)testWaitForBlock {
TestNeedsToWaitForBlock();
[target selectorWithInlineBlock:^(id obj) {
// assertions
BlockFinished();
}];
WaitForBlock();
}
答案 1 :(得分:4)
不确定您是否已经尝试过,但我使用Kiwi对我的iOS应用程序进行单元测试。它没有令人惊讶的记录,但它可以用于测试块。
https://github.com/allending/Kiwi
看看他们维基上“模拟和存根”下的“捕获参数”。您可以使用它来捕获正在传递的块。这对于异步代码非常有用 - 您可以调用要测试的方法,捕获一些完成块,然后立即同步执行块,使您的异步代码有效同步。
在提到感觉像起草实现的块时 - 它们不一定是那样的。我将块定义为一种方法,而不是内联。事实上,我经常编写一个方法来返回块,使代码干净且易于测试。
不确定那是不是你要找的东西。
答案 2 :(得分:0)
- (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];
}