如何对使用类方法的某些方法进行单元测试

时间:2013-12-05 03:50:41

标签: objective-c unit-testing dependency-injection

假设我有一个这样的方法,我想测试它并使用类方法:

@implementation User
...

- (void)methodToTest
{
    NSString *retval = [UserResourceTable staticMethod];
    // do something here
}

@end

由于UserResourceTable未被注入,并且它是一个类而不是实例的消息,因此它并不适合我,因为它适合于模拟。我不希望真正的方法执行,因为它会导致网络访问。

Similar question is asked for C#。杰伊说:“这是以这种方式使用静态的有时候不赞成的原因之一”,虽然这不仅仅是类方法的方式,还有很多Apple自己的库使用它?

给出的建议是将它包装在适配器中,以便可以将其发送到对象实例,并将其注入构造函数中。

说我像这样包裹它:

@implementation UserResourceWrapper
- (NSString *)staticMethodWrapper
{
    return [UserResourceTable staticMethod];
}
@end

我不太喜欢注射部分。我想我不希望它暴露在外部。所以我仍然最终继承User class的子类并创建一个工厂方法来返回,并让methodToTest调用它

@implementation User
- (NSString *)urt
{
    return [UserResourceTableWrapper new];
}

- (void)methodToTest
{
    NSString *retval = [[self urt] staticMethod];
    // do something here
}
@end

在单元测试中,我会将我要测试的类子类化为User并覆盖该urt:方法。这看起来很多工作。我能想到的另一种可能的方法是调动[UserResourceTable staticMethod]。这对工作来说看起来很麻烦。冒着被标记为不是一个好的常见问题解答格式的问题,在StackOverFlow(wink)上如此臭名昭着,这里的标准做法是什么?是否有一个现成的库来调酒?它看起来不像OCMock或OCMockito这样做,它们似乎只能在注入时使用。

修改

我感觉注射是最好的方式。使用子类化+工厂方法,如果我想为不同的测试用例提供不同的行为(例如成功案例和失败案例)。我需要两个模拟类,每个类提供不同的行为。对于一些测试来说,这是很多锅炉板。有了调配,一旦你换掉它就可以换掉它,它会在所有的测试中生效。但是,如果我可以注入它,可以在单元测试方法中创建模拟并且看起来很容易。

1 个答案:

答案 0 :(得分:1)

您要做的是注入UserResourceTableWrapper。以下是使用属性的setter注入的示例:

@property (nonatomic, strong) Class userResourceTableWrapperClass;

然后而不是直接调用

[UserResourceTableWrapper staticMethod]
你打电话

[self.userResourceTableWrapperClass staticMethod]

您可以使用各种形式的依赖注入来完成此任务:

  • 物业注入(如上所示)
  • 构造函数注入(即通过初始化程序参数)
  • 方法参数注入(如果使用范围有限)

提取和覆盖是另一种可能性,但我尝试将其限制为遗留代码。