stub [[SomeClazz alloc] init]不起作用,但接受的答案说它应该可以工作

时间:2016-06-06 09:45:51

标签: ios objective-c unit-testing ocmock

我的测试功能非常简单:

@implementation MyHandler
...
-(void) processData {
  DataService *service = [[DataService alloc] init];
  NSDictionary *data = [service getData];
  [self handleData:data];
}

@end

我使用OCMock 3对其进行单元测试。

我需要存根 [[DataService alloc] init]才能返回模拟实例,我尝试了answer from this question(这是一个已接受的答案)来存根[[SomeClazz alloc] init]

// Stub 'alloc init' to return mocked DataService instance,
// exactly the same way as the accepted answer told
id DataServiceMock = OCMClassMock([DataService class]);
OCMStub([DataServiceMock alloc]).andReturn(DataServiceMock);
OCMStub([DataServiceMock init]).andReturn(DataServiceMock);

// run function under test
[MyHandlerPartialMock processData];

// verify [service getData] is invoked
OCMVerify([dataServiceMock getData]);

我在测试中设置了断点,我确信在运行单元测试时会调用[service getData],但我的上述测试代码(OCMVerify)失败了。为什么?

是否因为正在测试的功能未使用我的模拟 DataService?但该问题中接受的答案告诉它应该有效。我现在感到困惑......

我想知道如何使用OCMock存储[[SomeClazz alloc] init]来返回模拟实例?

1 个答案:

答案 0 :(得分:0)

你不能模拟init,因为它是由模拟对象本身实现的。模仿init在您链接的答案中起作用的原因是因为它是自定义初始化方法。如果您不想使用依赖注入,则必须为init编写一个可以模拟的自定义DataService方法。

在您的实施中添加自定义init方法:

// DataService.m
...
- (id) initForTest
{
    self = [super init];
    if (self) {
        // custom initialization here if necessary, otherwise leave blank
    }

    return self;
}
...

然后更新MyHandler实施以调用此initForTest

@implementation MyHandler
...
-(void) processData {
  DataService *service = [[DataService alloc] initForTest];
  NSDictionary *data = [service getData];
  [self handleData:data];
}

@end

最后将测试更新为存根initForTest

id DataServiceMock = OCMClassMock([DataService class]);
OCMStub([DataServiceMock alloc]).andReturn(DataServiceMock);
OCMStub([DataServiceMock initForTest]).andReturn(DataServiceMock);

// run function under test
[MyHandlerPartialMock processData];

// verify [service getData] is invoked
OCMVerify([dataServiceMock getData]);

只要没有initForTest ,就可以重命名init