假设我有一个非常常见的使用UserDefaults
的属性 Package 器的用例。
@propertyWrapper
struct DefaultsStorage<Value> {
private let key: String
private let storage: UserDefaults
var wrappedValue: Value? {
get {
guard let value = storage.value(forKey: key) as? Value else {
return nil
}
return value
}
nonmutating set {
storage.setValue(newValue, forKey: key)
}
}
init(key: String, storage: UserDefaults = .standard) {
self.key = key
self.storage = storage
}
}
我现在声明一个对象,该对象将保存存储在UserDefaults
中的所有值。
struct UserDefaultsStorage {
@DefaultsStorage(key: "userName")
var userName: String?
}
现在,当我想在某个地方使用它时,比如说在视图模型中,我会有这样的东西。
final class ViewModel {
func getUserName() -> String? {
UserDefaultsStorage().userName
}
}
这里几乎没有问题。
1.在这种情况下,我似乎不得不使用.standard
用户默认值。如何使用UserDefaults
的其他/模拟示例测试该视图模型?
1.如何使用UserDefaults
的其他/模拟示例测试该属性 Package 器?我是否必须创建一个新类型,它是上述DefaultsStorage
的干净副本,传递模拟的UserDefaults
并测试该对象?
struct TestUserDefaultsStorage {
@DefaultsStorage(key: "userName", storage: UserDefaults(suiteName: #file)!)
var userName: String?
}
2条答案
按热度按时间rpppsulh1#
正如@mat在注解中提到的,你需要一个
protocol
来模拟UserDefaults
依赖。然后,您可以更改
DefaultsStorage
属性Wrapper以使用UserDefaultsStorage
引用而不是UserDefaults
:之后,模拟
UserDefaultsStorage
可能如下所示:要测试
DefaultsStorage
,请传递UserDefaultsStorageMock
的示例作为其存储参数:oxalkeyp2#
这可能不是最好的解决方案,但是,我还没有找到一种方法来将使用属性 Package 器的
UserDefaults
注入到ViewModel
中。如果有这样的选择,那么gcharita使用另一种协议的建议将是一个很好的实现。我在测试类中使用了与
ViewModel
中相同的UserDefaults
。我在每次测试之前保存原始值,并在每次测试之后恢复它们。