2

我正在为一个Foo具有协作者的类编写单元测试Bar。我想使用BarinFoo的测试的手动构建存根实现。

如果我在 Java 中这样做,我会给Foo一个BarFactory合作者并注入一个MockBarFactoryinFoo的测试,它总是返回我的StubBar.

我知道这种技术在 Objective-C 中可以很好地工作,但它并没有让我觉得在动态语言中做特别惯用的事情。我想知道我是否可以在运行单元测试时做任何会导致[[Bar alloc] init]返回StubBarBar在“现实生活”中正常实现的事情。

还是在这种情况下最适合使用明显的工厂模式?

4

2 回答 2

1

您可以在 中返回不同的对象init。这就是为什么你应该分配 to 的返回[super init]self。尝试这样的事情:

@implementation Bar 

- (id)init {
    if (UNIT_TEST) {
        self = [[StubBar alloc] init];
        if (self) {
            // do unit test init here
        }
    } else {
        self = [super init];
        if (self) {
            // do regular init here
        }
    }
    return self;
}

...

@end

注意:这应该在 ARC 下工作。如果您不使用 ARC,请确保self在分配新StubBar实例之前 release 。


如果您想避免将单元测试相关代码编译到您的主要目标中:

@implementation Bar 

- (id)init {
#if UNIT_TEST
    self = [[StubBar alloc] init];
    if (self) {
        // do unit test init here
    }
#else
    self = [super init];
    if (self) {
        // do regular init here
    }
#endif
    return self;
}

...

@end

如果您想完全分离单元测试和真实代码,您可以只拥有两个不同版本的Bar类。一个将使用真实代码编译,另一个将使用单元测试目标。


您可以轻松地分配实例,而无需在编译时知道确切的类类型,如下所示:

id someBar = [[someClass alloc] init]; // assuming someClass is of type Class

或者:

id someBar = [[NSClassFromString(@"Bar") alloc] init];

不过第一个比较好。您可以使用它来拥有一个默认的类类型,您可以在进行单元测试时更改它。可以作为Foo自身的属性,也可以作为您在单元测试时重新定义的预处理器宏。

于 2013-05-16T10:00:53.457 回答
0

您正在寻找的是类似于OCMock的东西。它允许您从类、协议构建模拟对象,并且它专门用于单元测试。

于 2013-05-16T10:59:15.717 回答