如何在Objective-C中对init方法进行单元测试?

3

我正在使用Xcode 5中的新的XCTest框架对Mac应用程序进行单元测试。具体而言,我正在尝试测试一个类是否实现了一个(尚未编写!)- (id)initWithStream:(NSInputStream)stream方法。因此,我开始编写我的测试:

- (void)testInitWithStream
{
  // Should have an init method named initWithStream:
  XCTAssertTrue([[MYParser alloc]
                 respondsToSelector:@selector(initWithStream:)],
                @"'initWithStream:' not implemented.");

前面的部分没有问题;目前测试按预期失败。接下来的部分尝试运行尚未编写的方法,这是导致我烦恼的原因:

  // Should return nil if no valid stream is passed
  XCTAssertNil([[MYParser alloc]
                  performSelector:@selector(initWithStream:)
                  withObject:nil], 
                 @"should get nil on 'initWithStream:' with no stream.");

Xcode给出了错误提示:“PerformSelector names a selector which retains the object.” 我使用了performSelector:withObject:,因为直接调用该选择器会导致错误:“No visible @interface for 'MYParser' declares the selector 'initWithStream:'.”
我的测试套件关闭了GCC_WARN_UNDECLARED_SELECTOR,但这些是错误而不是警告。当测试需要覆盖方法可能尚未实现(即使作为定义)的情况时,我该如何测试对象的init方法?
由于我是先编写测试,所以该方法可能尚未实现;这种做法是否正确?或者应该先编写类定义,然后编写测试和实际实现呢?(我寻求共识和最佳实践,而不仅仅是意见。)
1个回答

5

如果你正在进行测试驱动开发,那么你不需要为respondsToSelector:@selector(initWithStream:)进行测试。直接在你的测试套件中调用initWithStream:将无法编译。这是你需要修复的失败测试,在编写新代码之前解决它。你该如何修复?通过实现该方法:

- (instancetype)initWithStream:(id)stream {
    return [super init];
}

你的测试现在已经编译通过了,这比之前好一点。然而运行测试会失败,因为显然实现没有做你要测试的事情。现在编写更多代码使测试真正通过:

- (instancetype)initWithStream:(id)stream {
    if (!stream) {
        return nil;
    }
    return [super init];
}

接下来,您可以测试stream不是nil,但这将失败,因此您需要编写更多的代码来解决问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接