简体   繁体   English

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

[英]How to unit test some method that uses a class method

Say I have a method like this I want to test and it uses class methods: 说我有一个要测试的方法,它使用类方法:

@implementation User
...

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

@end

Since UserResourceTable is not injected and it is a message to a class and not a instance, it doesn't look to me like it is amenable to mocking. 由于没有注入UserResourceTable并且它是向类而不是实例的消息,因此在我看来它并不适合模拟。 I don't want the real method to execute, as it incurs network access. 我不希望执行真正的方法,因为它会导致网络访问。

Similar question is asked for C# . 对C#提出了类似的问题 Jay says "This is one of the reasons that using statics in this way is sometimes frowned upon", though isn't that just the way with class methods and plenty of Apple's own libraries use it? 杰伊说:“这是有时不赞成使用静态方法的原因之一”,尽管这不只是类方法和苹果自己的大量库使用它的方式吗?

The advices given are to wrap it in an adapter so it can be messaged to an object instance instead and to inject it in the constructor. 给出的建议是将其包装在适配器中,以便可以将其发送给对象实例,然后将其注入构造函数中。

Say I wrapped it like this: 假设我像这样包裹它:

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

I am not so fond of the injection part. 我不太喜欢注射部分。 I think I do not want it to be exposed externally. 我想我不希望它在外部公开。 So I still end up subclassing the User class and create a factory method to return, and have methodToTest calls it 因此,我仍然最终methodToTestUser class并创建了一个要返回的工厂方法,并让methodToTest调用

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

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

In unit test, I would subclass the class I want to test which is User and override that urt: method. 在单元测试中,我将要测试的类作为User子类,并重写urt:方法。 That looks like a lot of work. 看起来需要很多工作。 Another possible method I can think of is to swizzle [UserResourceTable staticMethod] . 我能想到的另一种可能的方法是[UserResourceTable staticMethod] This looks like a lot of trouble for the job. 这项工作看起来很麻烦。 Risking for being marked as not in a good FAQ format blah blah so infamous on StackOverFlow (wink), what's the standard practice here? 冒被标记为不是很好的FAQ格式的风险等等在StackOverFlow(眨眼)上臭名昭著,这里的标准做法是什么? Is there a ready-made library to swizzle? 有现成的图书馆可供选择吗? It doesn't look like OCMock or OCMockito can do this, they appear to be able to be used only when injected. 看起来OCMock或OCMockito不能做到这一点,它们似乎只能在注射时使用。

EDIT: 编辑:

I'm getting the feeling that injection is the best possible way. 我感觉注射是最好的方法。 With subclassing + factory method, if I want to provide different behaviors for different test cases (success case & failure case, for example). 如果要为不同的测试用例(例如成功案例和失败案例)提供不同的行为,则使用子类+工厂方法。 I would need two mock classes each providing a different behavior. 我需要两个模拟类,每个模拟类提供不同的行为。 That's a lot of boiler plates for a few tests. 对于一些测试,这是很多样板。 With swizzle, once you swap it you swap it for good and it takes effect in all the tests. 使用swizzle,一旦将其交换,就可以将其永久交换,并且在所有测试中都有效。 However if I can inject it, the mock can be created right within the unit-testing method and seems easy-peasy. 但是,如果可以注入它,则可以在单元测试方法中直接创建该模拟,并且看起来很简单。

What you want to do is inject UserResourceTableWrapper . 您要做的是注入UserResourceTableWrapper Here's an example using setter injection using a property: 这是一个通过属性使用setter注入的示例:

@property (nonatomic, strong) Class userResourceTableWrapperClass;

Then instead of directly calling 然后,而不是直接调用

[UserResourceTableWrapper staticMethod]

you'd call 你会打电话

[self.userResourceTableWrapperClass staticMethod]

You can accomplish this using the various forms of dependency injection: 您可以使用各种形式的依赖项注入来完成此操作:

  • Property injection (shown above) 属性注入(如上所示)
  • Constructor injection (that is, through initializer argument) 构造函数注入(即通过初始化参数)
  • Method argument injection (if use has limited scope) 方法参数注入(如果使用的范围有限)

Extract and Override is another possibility, but I try to limit it to legacy code. 提取和覆盖是另一种可能性,但我尝试将其限制为旧代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM