Right, so I have finally gotten to the bottom of this and its not pretty. There is actually a radar for this issue as it appears to be a bug with the Swift compiler not recognizing ManagedObject casting in test targets. So add your voice to the noise
Starting off with an entity defined as follows:
@objc(Member)
class Member: NSManagedObject {
@NSManaged var name: String
}
I wrote a simple test class in which I create a MO in 3 different ways:
The first two failed:
let context = NSManagedObjectContext.MR_defaultContext()
func testMagicalRecordCreation() {
let m = Member.MR_createInContext(context) as? Member
XCTAssertNotNil(m, "Failed to create object")//fails
}
func testEntityDescriptionClassCreation() {
let m2 = NSEntityDescription.insertNewObjectForEntityForName("Member", inManagedObjectContext: context) as? Member
XCTAssertNotNil(m2, "Failed to create object")//fails
}
And then a success
func testManualMOCreation() {
let ent = NSEntityDescription.entityForName("Member", inManagedObjectContext: context)!
let m3 = Member(entity: ent, insertIntoManagedObjectContext: context)
XCTAssertNotNil(m3, "Failed to create object")
}
This means that right now you have two options. Write your tests in Objective-C; or create a utility method to insert test objects into a context using the means I showed above.
Theres a nice post about this behaviour here
I ended up using an NSManagedObjectContext extension to be used explicitly in Swift Tests:
extension NSManagedObjectContext {
func insertTestEntity<T: NSManagedObject>(entity: T.Type) -> T {
let entityDescription = NSEntityDescription.entityForName(NSStringFromClass(T.self), inManagedObjectContext: self)!
return T(entity: entityDescription, insertIntoManagedObjectContext: self)
}
}
And it could be used like this:
func testConvenienceCreation() {
let m4 = context.insertTestEntity(Member)
XCTAssertNotNil(m4, "Failed to create object")
}
More reading about this kind of approach here
insertNewObjectForEntityForName
etc ? – Hydrostatic