我有一个名为Gift的托管对象,它具有属性
import Foundation
import CoreData
class Gift: NSManagedObject {
@NSManaged var name: String
@NSManaged var price: NSNumber
@NSManaged var location: String
}
使用单个单元测试然后我成功地将实体插入到Core Data中(没有错误)。
func testThatWeCanSaveGift() {
let entity = NSEntityDescription.entityForName("Gift", inManagedObjectContext: managedObjectContext!)
let gift = Gift(entity: entity!, insertIntoManagedObjectContext: managedObjectContext!)
gift.name = "Test"
gift.price = 10.0
gift.location = "London"
XCTAssertNotNil(gift, "Unable to create a gift")
var error: NSError? = nil
managedObjectContext?.save(&error)
XCTAssertNil(error, "Failed to save the context with error \(error), \(error?.userInfo)")
为了测试这是否完全成功,我然后使用获取请求返回此数据。
let fetchRequest: NSFetchRequest = NSFetchRequest(entityName: "Gift")
var requestError: NSError? = nil
if let gifts = managedObjectContext?.executeFetchRequest(fetchRequest, error: &requestError) {
let aGift: NSManagedObject = gifts.first as! NSManagedObject
//println("Gift name: \(aGift.name)")
let string: String? = aGift.valueForKey("name") as? String
println("Name: \(string)")
var bGift: Gift = aGift as! Gift
println("Name: \(bGift.name)")
var a = 1
}
}
当我运行此测试时,在使用错误EXC_BAD_ACCESS(code = 1,address = 0x8)将aGift转换为bGift var bGift: Gift = aGift as! Gift
的行上失败。但是,我确实从aGift中的Core Data获得了结果,但是作为NSManagedObject
只有当我在单元测试中运行代码时才会发生这种情况,如果我在应用程序中运行它,它会返回正确的信息并正确地投射它。
我在测试时做错了什么?
答案 0 :(得分:1)
在此页面上找到答案(问题后的第一个答案)Swift and CoreData Casting issues in test vs non-test
我无法强制转换的原因是NSManagedObject(Gift)完全限定的类名是MY_PROJECT.Gift,但是当测试运行时,它会尝试将其强制转换为MY_PROJECT_TESTS.Gift。为了解决这个问题,我从核心数据模型UI中的实体的类名中删除了MY_PROJECT,因此它只读取了Gift。然后我重新编写了managedObjectModel代码。
lazy var managedObjectModel: NSManagedObjectModel = {
// The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
let modelURL = NSBundle.mainBundle().URLForResource("GiftReminder", withExtension: "momd")!
let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!
// Check if we are running as test or not
let environment = NSProcessInfo.processInfo().environment as! [String: AnyObject]
let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"
// Create the module name
let moduleName = (isTest) ? "GiftReminderTests" : "GiftReminder"
// Create a new managed object model with updated entity class names
var newEntities = [] as [NSEntityDescription]
for (_, entity) in enumerate(managedObjectModel.entities) {
let newEntity = entity.copy() as! NSEntityDescription
newEntity.managedObjectClassName = "\(moduleName).\(entity.name)"
newEntities.append(newEntity)
}
let newManagedObjectModel = NSManagedObjectModel()
newManagedObjectModel.entities = newEntities
return newManagedObjectModel
}()
这将动态检查我是否正在运行测试并使用正确的预修复程序。