如何使用NSUserDefaults进行测试?

时间:2010-10-20 13:03:30

标签: cocoa unit-testing nsuserdefaults

在我的大多数使用默认值的类中,我使默认对象可设置为:

@property(retain) NSUserDefaults *defaults;

这应该会使测试变得更容易:

// In a nearby test class:
- (void) setUp {
    [super setUp];
    NSUserDefaults *isolatedDefaults = [[NSUserDefaults alloc] init];
    [someObjectBeingTested setDefaults:isolatedDefaults];
}

但是现在我发现当我创建一个新的默认对象时,它已经有了一些值。那可能吗?我以为我可以通过调用-init来创建一个空的,独立的默认对象。我是否在测试代码中的某处有错误,或者如果我想测试基于默认值的代码,我是否真的需要做一些更复杂的事情(如存根或模拟)?

3 个答案:

答案 0 :(得分:8)

最后,我创建了一个简单的NSUserDefaults替换,可用于控制测试中的默认环境。该代码可在GitHub上找到。

答案 1 :(得分:6)

来自NSUserDefaults文档:

  

init:返回使用当前用户帐户的默认值初始化的NSUserDefaults对象。

通常不应为空。我不确定你想在这里测试什么,因为测试NSUserDefaults功能会浪费时间。

但是说你需要一些键尚未注册,你的测试总是有相同的初始点:然后只需在setUp中删除它们(如果你愿意,可以在tearDown中恢复它们)。

类似的东西:

- (void) setUp {
  [super setUp];

  [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"myTestKey"];

  // synchronize the change, or just use resetStandardUserDefaults:
  [someObjectBeingTested setDefaults:[NSUserDefaults resetStandardUserDefaults]];
}

如果您没有特定的密钥列表但需要清除所有密钥,则必须使用CoreFoundation首选项实用程序,请参阅CFPreferencesCopyKeyList。

答案 2 :(得分:0)

我们还需要覆盖NSUserDefaults进行测试,但不想更改任何应用程序代码。

因此我们在NSUserDefaults上编写了一个类别,允许我们在运行时使用方法调配覆盖objectForKey:返回的值。

在Objective C中看起来像这样:

NSLog(@"Value before: %d", [[NSUserDefaults standardUserDefaults] boolForKey:@"Example"]);
// Value before: 0

[[NSUserDefaults standardUserDefaults] overrideValue:@(YES) forKey:@"Example"];

NSLog(@"Value after: %d", [[NSUserDefaults standardUserDefaults] boolForKey:@"Example"]);
// Value after: 1

在Swift中就像这样:

print(UserDefaults.standard.bool(forKey: "ExampleKey")) // false

UserDefaults.standard.overrideValue(true, forKey: "ExampleKey")

print(UserDefaults.standard.bool(forKey: "ExampleKey")) // true

您可以在Github上找到我们的代码:https://github.com/jakob/NSUserDefaultsOverride