2016-08-15 1 views
2

zu verspotten Ich benutze realm-cocoa für meine Persistenz-Schicht. Es ist eine der Klassen in Abhängigkeit von realmWie Real-Kakao in Swift

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 
} 

Da ist in meinem Test-Code, ich verspottet Version von RealmInterface schreiben kann und injizieren es in die RealmMetaData Instanz mit Constructor Injection.

Bei der Umsetzung der verspotteten RealmInterface, fand ich, dass es sehr schwierig ist, die objects Funktion zu verspotten, um eine leere Liste zurückzugeben. Da der Rückgabetyp der Funktionssignatur Results<T> ein Typ ist, der von Realm Framework bereitgestellt wird, und kein leerer Konstruktor verfügbar ist. Hier stecke ich fest.

Das Result<T> ist eine Klasse mit final Schlüsselwort, also kann ich es auch nicht ableiten, um seine privaten Methoden zu verwenden, um eine leere Sammlung zu holen.

Vielen Dank im Voraus!

+0

Der erste Vorschlag, der Ihnen in den Sinn kommt, besteht darin, In-Memory-Realm in Ihrer Testklasse zu behalten und zu verwalten und all diese Methoden weiterzuleiten. – Dmitry

+0

@Dmitry Ja, das hat geholfen, danke. Würden Sie diesen Kommentar als Antwort schreiben, dann kann ich das akzeptieren? –

Antwort

1

Wie ich in einem Kommentar vorgeschlagen habe, können Sie einfach einen internen speicherinternen Realm innerhalb Ihrer Testklasse verwenden und alle Methoden weiterleiten, die Result<T> zurückgeben.

0

Ich gebe am Ende mein eigenes Protokoll anstelle der Ergebnisse zurück. Also habe ich die Implementierung dieses Protokolls mit AnyRealmCollection<T> und die andere mit nur [T], so dass ich es leicht in Tests ohne Real-Objekt im Speicher spotten.

+0

Obwohl ich diesen Ansatz verstehe, ist es keine gute Übung, Ihren Code zu ändern, um das Testen auf diese Weise zu erleichtern. –

+0

@KevinR wegen was? – ReDetection

+0

Meine zwei Cent, aber ändernden Code zu erleichtern führt zu mehr Komplexität und damit zu möglichen Fehlern. Darüber hinaus kann die Änderung von Implementierungen während des Tests dazu führen, dass Sie glauben, der Code liefe gut, wenn die im Produktionscode verwendete Darstellung in Wirklichkeit zu unterschiedlichen Ergebnissen führen könnte. –