Reputation: 5669
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).
Here are the steps to set up the smallest reproducible example I could come up with:
Entity
(Person
) with one Attribute
(name
, type String
). Person
is unique, name
is non-optional.@objc(Person)
in Person.swift
to avoid a build error.)unique
property.) Here's the ViewController
that'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.") }
}
}
Person
subclass files to SOTestTests
(meta, I know) in Build Phases, setup the managedObjectContext
according 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.") }
}
}
SOTestTests
, and addthe SOTest.app
executable 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?
Upvotes: 1
Views: 899
Reputation: 80271
Just import the actual project to get access to AppDelegate and other classes.
@testable import SOTest
No need to add everything to the test target.
Upvotes: 4