如何在swift中模拟realm-cocoa

时间:2016-08-15 09:55:12

标签: swift unit-testing realm

我正在使用realm-cocoa作为持久层。其中一个课程取决于realm

class RealmMetaData : AbstractMetaData {
    var realm: RealmInterface
    var isFirstLaunch: Bool = false
    init(realm: RealmInterface = try! Realm()) {
        self.realm = realm
        let results = realm.objects(MyClass.self)
        self.isFirstLaunch = (results.count == 0)
        if (self.isFirstLaunch) {
            realm.write {
                realm.add(MyClass())
            }
        }
    }
    // some code
}


protocol RealmInterface {
    // using a protocol based approach of mocking
    func objects<T: Object>(type: T.Type) -> Results<T>
    func write(@noescape block: (() throws -> Void)) throws
    func add(object: Object)
}

extension Realm: RealmInterface {
    func add(object: Object) { self.add(object, update: false) }
    // there is a method for Realm with signature: add(object:Object, update:Bool = false)
    // but swift extension dose not permit default function parameter, hence the wrapping
}

然后在我的测试代码中,我可以编写RealmInterface的模拟版本并使用Constructor Injection将其注入RealmMetaData实例。

在实现模拟RealmInterface时,我发现很难模拟objects函数返回空列表。因为函数签名Results<T>的返回类型是Realm Framework提供的类型,并且没有可用的空构造函数。这就是我被困住的地方。

Result<T>是一个带有final关键字的类,所以我也不能将它子类化为使用它的私有方法来获取空集合。

提前致谢!

2 个答案:

答案 0 :(得分:1)

正如我在评论中建议的那样,您可以在测试类中使用内部内存中的Realm,并将所有返回Result<T>的方法转发给它。

答案 1 :(得分:0)

我最终返回自己的协议而不是结果。所以我用AnyRealmCollection<T>实现了这个协议,而只用[T]实现了这个协议,所以我很容易在没有任何内存中Realm对象的测试中模拟它。