Swift单元测试EXC_BAD_ACCESS(代码= 1,地址= 0x8)

时间:2015-05-26 09:57:59

标签: ios xcode swift unit-testing core-data

我有一个名为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

只有当我在单元测试中运行代码时才会发生这种情况,如果我在应用程序中运行它,它会返回正确的信息并正确地投射它。

我在测试时做错了什么?

1 个答案:

答案 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
    }()

这将动态检查我是否正在运行测试并使用正确的预修复程序。