In a Nutshell:
I'm trying to write a unit test for a Core Data model in XCode 7/Swift 2. However, a simple test such as testing that the number of rows in the model is equal to what I know it to be fails (I know there to be one row, but the test sees none). My best guess is that I'm getting a different (clean?) version of managedObjectContext, but I'm not sure how to get the same version as the app. Besides the technique described below (following the linked instructions on Andrew Bancroft's site), I tried adding the application delegate to SOTestTests and getting the managedObjectContext as follows...
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
...but I then get an error that XCode [c]ould not cast value of type 'SOTest.AppDelegate' (0x25bb8) to 'SOTestTests.AppDelegate' (0x2c7bb78).
Longform:
Here are the steps to set up the smallest reproducible example I could come up with:
- Simple model: One
Entity(Person) with oneAttribute(name, typeString).Personis unique,nameis non-optional. - Create a subclass (Editor > Create NSManagedObject Subclass...)
- (Comment out
@objc(Person)inPerson.swiftto avoid a build error.) - Add a single row to the model. (Only run the code that gets an entity and saves it once--comment it out on subsequent runs to avoid getting a conflict error due to the
uniqueproperty.) Here's theViewControllerthat's doing this:
import UIKit
import CoreData
class ViewController: UIViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
// Put a new person in the model.
let newPerson = NSEntityDescription.insertNewObjectForEntityForName("Person", inManagedObjectContext: self.managedObjectContext) as! Person
newPerson.name = "Harper Lee"
// Save it
do { try self.managedObjectContext.save()
} catch _ { NSLog("There was a problem saving to the database.") }
// Sanity check
let fetchRequest = NSFetchRequest(entityName:"Person")
do {
let fetchedResults = try managedObjectContext.executeFetchRequest(fetchRequest) as? [Person]
NSLog("Number of rows (App): \(fetchedResults!.count)") // 1
} catch _ { NSLog("Well...that went badly.") }
}
}
- I then add the
Personsubclass files toSOTestTests(meta, I know) in Build Phases, setup themanagedObjectContextaccording to the example on Andrew Bancroft's (excellent) site (with mods for Swift 2), and write the test checking if there is one row:
import XCTest
import CoreData
class SOTestTests: XCTestCase {
var managedObjectContext: NSManagedObjectContext!
func setUpInMemoryManagedObjectContext() -> NSManagedObjectContext {
let managedObjectModel = NSManagedObjectModel.mergedModelFromBundles([NSBundle.mainBundle()])!
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
do {
try persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil)
} catch _ { NSLog("Problem adding the Persistent Store Coordinator") }
let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator
return managedObjectContext
}
override func setUp() {
super.setUp()
self.managedObjectContext = self.setUpInMemoryManagedObjectContext()
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// Check the number of rows in NUT_DATA
do {
let fetchRequest = NSFetchRequest(entityName:"Person")
let fetchedResults = try managedObjectContext.executeFetchRequest(fetchRequest) as? [Person]
print("Number of rows (Test): \(fetchedResults!.count)") // Prints 0
XCTAssert(1 == fetchedResults!.count, "Incorrect number of rows in `Person` entity.")
} catch _ { NSLog("Error fetching the entity Person.") }
}
}
- Create a new scheme by selecting
SOTestTests, and addtheSOTest.appexecutable to the run scheme.
When I run this, the ViewController class prints out that there is a single row, but the test prints out zero rows, and the test fails.
Any ideas what I'm doing wrong?
Aucun commentaire:
Enregistrer un commentaire