这是我的类(class)的简化版本:
@interface RTMovieBuilder : NSObject
@property (atomic, getter = isCancelled) volatile BOOL cancelled;
@property (nonatomic, weak) id<BuilderDelegate>delegate;
- (void)moviesFromJSON:(id)JSON;
- (Movie *)movieFromDictionary:(NSDictionary *)dict;
- (void)cancel;
@end
@implementation RTMovieBuilder
- (void)moviesFromJSON:(id)JSON
{
// Check for errors -> If good, then do...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self syncrouslyCreateMoviesFromJSON:JSON];
});
}
- (void)syncrouslyCreateMoviesFromJSON:(id)JSON
{
NSMutableArray *movies = [NSMutableArray array];
for (NSDictionary *dict in JSON)
{
if ([self isCancelled])
return;
else
[movies addObject:[self movieFromDictionary:dict]];
}
[self notifyDelegateCreatedObjects:movies];
}
- (Movie *)movieFromDictionary:(NSDictionary *)dict
{
Movie *movie = [[Movie alloc] init];
// Set movie properties based on dictionary...
return movie;
}
- (void)cancel
{
[self setCancelled:YES];
}
// ... Other methods omitted for brevity's sake
@end
属性cancelled
是atomic
和volatile
因为它可以被其他线程访问(即主线程可以调用cancel
方法来停止操作)。 (我相信这些是必需的,如果不需要,请注意为什么它不在您的答案中。)
我正在尝试编写单元测试以确保它在编写 View Controller 类之前能够正常工作。
当 RTMovieBuilder
正在创建 movies
时,我如何编写一个单元测试来模拟对 cancel
的调用?
编辑
这是我已经编写的单元测试,这些测试可确保 notifyDelegateCreatedObjects:
在首先调用 cancel
时不会被调用。
- (void)testIfCancelledDoesntNotifyDelegateOfSuccess
{
// given
RTMovieBuilder *builder = [[RTMovieBuilder alloc] init];
builder.delegate = mockProtocol(@protocol(BuilderDelegate));
// when
[builder cancel];
[builder notifyDelegateCreatedObjects:@[]];
// then
[verifyCount(builder.delegate, never()) builder:builder createdObjects:anything()];
}
我正在使用 OCHamcrest
和 OCMockito
。该测试通过。
最佳答案
我会避免尝试在单元测试中模拟线程时序,而是更专注于找出所有可能的最终状态,而不管时序落在何处,并在这些条件下编写代码测试。正如 bbum 也指出的那样,这可以避免测试中无穷无尽的复杂性。
在您的情况下,您需要测试的条件似乎是对 notifyDelegateCreatedObjects
的调用是否发生在操作取消之后,因为取消来得太晚了。因此,只需在您的 notifyDelegateCreatedObjects
方法中对下游场景的处理进行单元测试,或者由于线程计时而通知该中止事件的任何类。
我知道这不是您问题的具体答案,但我认为这是实现相同单元测试目标的更好方法。
关于ios - 如何对依赖于 Objective-C 中的 volatile 变量的方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21638266/