Skip to content

Instantly share code, notes, and snippets.

@bstien
Last active October 30, 2017 21:07
Show Gist options
  • Save bstien/cf378c280479520b918061573f8b36c8 to your computer and use it in GitHub Desktop.
Save bstien/cf378c280479520b918061573f8b36c8 to your computer and use it in GitHub Desktop.
Testing ViewModel with Core Data
import Foundation
import RxCoreData
import CoreData
// The entity's name in .xcdatamodeld is 'Item'. It has empty fields for both Class and Module. Codegen is 'Manual/None'.
struct Item {
var date: Date
}
extension Item: Persistable {
public typealias T = NSManagedObject
public static var entityName: String { return "Item" }
public static var primaryAttributeName: String { return "date" }
public var identity: String { return date.debugDescription }
public init(entity: T) {
date = entity.value(forKey: "date") as! Date
}
public func update(_ entity: NSManagedObject) {
entity.setValue(date, forKey: "date")
do {
try entity.managedObjectContext?.save()
} catch {
print(error)
}
}
}
import Foundation
import CoreData
import RxSwift
import RxCocoa
import RxCoreData
// The view-model I'm trying to test.
class ViewModel {
let items: Driver<[Item]>
let addItem = PublishSubject<Void>()
let disposeBag = DisposeBag()
let moc: NSManagedObjectContext
init(managedObjectContext: NSManagedObjectContext) {
moc = managedObjectContext
items = moc.rx.entities(Item.self, sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)]).asDriver(onErrorJustReturn: [])
addItem.bindNext {
let item = Item(date: Date())
do { try self.moc.rx.update(item) } catch { print(error) }
}.disposed(by: disposeBag)
}
}
import CoreData
import RxCoreData
import RxSwift
import RxTest
import Quick
import Nimble
@testable import CoreDataAppTarget
// Unit testing the view-model.
class ViewModelQuickTest: QuickSpec {
override func spec() {
var scheduler: TestScheduler!
var disposeBag: DisposeBag!
var moc: NSManagedObjectContext!
var subject: ViewModel!
beforeEach {
scheduler = TestScheduler(initialClock: 0)
disposeBag = DisposeBag()
moc = self.inMemoryStack()
subject = ViewModel(managedObjectContext: moc)
}
it("Adds an Item on events") {
let result = scheduler.createObserver([Item].self)
let addItem = scheduler.createColdObservable([next(100, ()), next(200, ())])
subject.items.drive(result).disposed(by: disposeBag)
addItem.bindTo(subject.addItem).disposed(by: disposeBag)
scheduler.start()
print(result.events.debugDescription)
}
}
func inMemoryStack() -> NSManagedObjectContext {
let modelURL = Bundle.main.url(forResource: "CoreDataModel", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL)!
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil)
} catch {
print("Adding in-memory persistent store failed")
}
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
return managedObjectContext
}
}
import XCTest
import CoreData
import RxCoreData
import RxSwift
@testable import CoreDataAppTarget
// General test for persisting objects.
class ViewModelTest: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
func testExample() {
let disposeBag = DisposeBag()
let moc = inMemoryStack()
let items = moc.rx.entities(Item.self, sortDescriptors: [NSSortDescriptor(key: "date", ascending: false)]).debug()
let item = Item(date: Date())
do { try moc.rx.update(item) } catch { print(error) }
items.subscribe { (event) in
print("--- event: " + event.debugDescription)
}.disposed(by: disposeBag)
}
func inMemoryStack() -> NSManagedObjectContext {
let modelURL = Bundle.main.url(forResource: "CoreDataModel", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL)!
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil)
} catch {
print("Adding in-memory persistent store failed")
}
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
return managedObjectContext
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment