我有一个带有方法X
的objective-c类turtle
,我想用OCMock模拟它来对一个类T
进行单元测试。
//X.h
@interface X
-(void) turtle;
@end
班级T
包含一个类别,并使用该类别与X
进行通信。类别方法调用turtle
。
//X+utils.h:
@interface X(Utils)
-(void) catMethod;
@end
//X+utils.m:
@implementation X(Utils)
-(void) catMethod
{
[self turtle];
}
@end
//T.m
#import "X+utils.h"
@implementation T
-(void) useX:(X*) xInstance
{
[xInstance catMethod];
}
在单元测试中,我设置了模拟,希望调用turtle
。
-(void) test
{
id mockX = [OCMockObject mockForClass:[X class]]
[[mockX expect] turtle];
[instanceOfT useX:mockX];
[mockX verify];
}
我没有设置模拟以期望调用类别的方法,因为我想让实现自由选择它喜欢使用的任何类别。
调用useX失败,因为OCMock捕获"意外"致电catMethod
。
我是否可以将OCMock配置为实际使用类别的实现,并且只模拟在实际接口X
中定义的调用?
答案 0 :(得分:1)
这里的关键是你要测试的东西。
在您的测试方法中,您正在测试useX:
,此方法的作用。采用纯单元测试方法,您应该测试它在x上调用catMethod
。
如果你想测试最终调用乌龟,你可以使用类似下面代码的部分模拟。但请记住,您不仅要测试T
useX:
,还要测试该类别中声明的catMethod
。
-(void) test
{
X *x = [[X alloc] init];
id partialX = [OCMockObject partialMockForObject:x]
[[partialX expect] turtle];
[instanceOfT useX:x];
[partialX verify];
}
答案 1 :(得分:0)
使用-mockForClass:返回一个对象,该对象将对发送给它的任何方法引发异常,而不是您存根或期望的方法。它实际上没有来自指定类的任何实现;它只是伪装成一个实例。 -niceMockForClass:不会引发意外的方法,而只是那些有拒绝的方法,但也不会做任何事情 - 它基本上就像每个方法都有一个空实现的类。
正如在另一个答案中所提到的,你真正想要的是部分模拟,它确实使用了相关类的实际实例。所有方法调用都将调用常规实现,除了那些你存根,期望或拒绝的实现(即使使用那些,你可以使用-andForwardToRealObject来调用原始实现)。