【问题标题】:OCUnit test for protocols/callbacks/delegate in Objective-COCUnit 测试 Objective-C 中的协议/回调/委托
【发布时间】:2010-11-07 20:14:27
【问题描述】:

使用 OCUnit,有没有办法测试委托协议?

我正在尝试这个,它不起作用。

-(void) testSomeObjDelegate {
  SomeObj obj = [[SomeObj alloc] initWithDelegate:self];
  [obj executeMethod];
}
-(void) someObjDelegateMethod {
  //test something here
}

我将尝试在不同的线程上调用obj 方法并让测试休眠,直到调用委托。似乎应该有一种更简单的方法来测试它。

【问题讨论】:

标签: objective-c unit-testing delegates ocunit


【解决方案1】:

请查看Unit Testing Asynchronous Network Access。我想可以帮助你。 简而言之,它的作用是:

添加以下方法来处理同步 在单元测试代码和被测异步代码之间:

- (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs {
    NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];

    do {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
        if([timeoutDate timeIntervalSinceNow] < 0.0)
            break;
    } while (!done);

    return done;
}

【讨论】:

  • 那个链接对我帮助很大!谢谢。
【解决方案2】:

测试委托很简单。只需在回调方法的测试中设置一个 ivar,并在应该触发委托回调后检查它。

例如,如果我有一个类 Something 使用协议 SomethingDelegate 的委托并发送该委托 -something:delegateInvoked: 以响应某些消息,我可以像这样对其进行测试:

@interface TestSomeBehavior : SenTestCase <SomethingDelegate>
{
    Something *_object;
    BOOL _callbackInvoked;
}
@end

@implementation TestSomeBehavior

- (void)setUp {
    [super setUp];
    _object = [[Something alloc] init];
    _object.delegate = self;
}

- (void)tearDown {
    _object.delegate = nil;
    [_object release];
    [super tearDown];
}

- (void)testSomeBehaviorCallingBack {
    [_object doSomethingThatShouldCallBack];

    STAssertTrue(_callbackInvoked,
                 @"Delegate should send -something:delegateInvoked:");
}

- (void)something:(Something *)something delegateInvoked:(BOOL)invoked {
    _callbackInvoked = YES;
}

@end

但是,我认为您已经从您提出问题的方式中理解了这一点。 (我主要是为其他读者发布此内容。)我认为您实际上是在问一个更微妙的问题:我如何测试以后可能发生的东西,例如旋转运行循环的东西。我的暗示是你提到的睡眠和穿线。

首先,您不应该随意调用另一个线程上的方法。只有在记录以这种方式使用是安全的情况下,您才应该这样做。原因是你不知道类的内部是做什么的。例如,它可能会在运行循环上安排事件,在这种情况下,在不同的线程上运行该方法会使它们发生在不同的运行循环上。这会搞砸类的内部状态。

如果您确实需要测试一些可能需要一点时间才能发生的事情,您可以通过运行当前的运行循环来做到这一点。以下是我可能会如何重写上面的单个测试方法来做到这一点:

- (void)testSomeBehaviorCallingBack {
    NSDate *fiveSecondsFromNow = [NSDate dateWithTimeIntervalSinceNow:5.0];

    [_object doSomethingThatShouldCallBack];

    [[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow];

    STAssertTrue(_callbackInvoked,
                 @"Delegate should send -something:delegateInvoked:");
}

这将使当前运行循环在默认模式下旋转 5 秒,假设 -doSomethingThatShouldCallBack 将在默认模式下将其工作安排在主运行循环上。这通常没问题,因为以这种方式工作的 API 通常允许您指定要使用的运行循环以及要运行的模式。如果可以做到这一点,那么您可以使用 -[NSRunLoop runMode:beforeDate:] 在该模式下运行运行循环相反,让您期望完成的工作更有可能完成。

【讨论】:

  • 这正是我遇到的问题。感谢您的简洁回答。这为我解决了。
  • 也许将委托功能封装在(模拟)对象中会使这个方法更好。我还在为异步回调寻找更自然的单元测试方法。
  • 最佳答案!帮我解决了问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-21
  • 2019-12-27
相关资源
最近更新 更多