Swift无法在Xcode测试中测试核心数据?

zum*_*zum 18 core-data ios swift

我正在开发一个使用核心数据的iOS项目.我正在使用swift.Core Data堆栈设置正确,一切似乎都没问题.我为一个名为TestEntity的实体(NSManagedObject)创建了一个类.这个类看起来像这样:

import UIKit
import CoreData

class TestEntity: NSManagedObject {
    @NSManaged var name: NSString
    @NSManaged var age: NSNumber
}
Run Code Online (Sandbox Code Playgroud)

那么,我尝试使用以下代码行在代码中插入一个新的TestEntity:

let te: TestEntity = NSEntityDescription.insertNewObjectForEntityForName("TestEntity", inManagedObjectContext: ctx) as TestEntity
Run Code Online (Sandbox Code Playgroud)

然后我得到这个错误:

在此输入图像描述

我已经看到堆栈溢出的一些答案,说我需要担心模块名称.那么我在文档上看了一下:https: //developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/WritingSwiftClassesWithObjective-CBehavior.html

然后我进入了TestEntity的核心数据实体,在类字段中我输入了myAppName.TestEntity

当我运行应用程序时这一行:

let te: TestEntity = NSEntityDescription.insertNewObjectForEntityForName("TestEntity", inManagedObjectContext: ctx) as TestEntity
Run Code Online (Sandbox Code Playgroud)

仍然给我同样的错误.

还有什么我可能做错了?

编辑:所以,通过将TestEntity NSManagedObject类更改为:导入UIKit导入CoreData,我能够使应用程序不再崩溃

@objc(TestEntity) class TestEntity: NSManagedObject {
    @NSManaged var name: NSString
    @NSManaged var age: NSNumber
}
Run Code Online (Sandbox Code Playgroud)

所以,我在其中添加了@objc(TestEntity).无论是否在核心数据数据模型检查器中的TestEntity类名称之前添加appName,都可以使用此方法.

这可行,但是,当我运行测试时,这一行仍然崩溃:

let te: TestEntity = NSEntityDescription.insertNewObjectForEntityForName("TestEntity", inManagedObjectContext: ctx) as TestEntity
Run Code Online (Sandbox Code Playgroud)

所以我发现这对其他人来说是个问题: 如何在测试目标中访问Core Data生成的Obj-C类?

我们如何才能让核心数据在swift中进行测试.我没有在应用程序目标中使用桥接头,它一切都很好.测试目标仍然崩溃.

如何修复测试目标以便运行核心数据测试?

joh*_*ord 20

使用Xcode 7,@testable您不再需要更新managedObjectClassName或使用其他黑客.以下是我在Xcode 7.2中使用它所做的工作.

  1. 设置测试目标Host Application并选中"允许测试主机应用程序API".

在此输入图像描述

  1. 确保您的常规类都没有指向Test目标的Target Membership.只有具有单元测试代码的类才应设置为测试目标.

在此输入图像描述

  1. 将该@testable行添加到所有测试类的顶部:
import XCTest
@testable import MyApp

class MyAppTests: XCTestCase {
}
Run Code Online (Sandbox Code Playgroud)

如果您仍然遇到问题,可以尝试以下附加提示:https://forums.developer.apple.com/message/28773#28949

我和这个人争了一段时间,所以我希望它可以帮助其他人.


Lud*_*dry 6

这是因为CoreData框架仍然在Objective-C中.Swift使用命名空间类,因此要让CoreData找到你的swift类,你必须用它的命名空间指定Class name,如下所示:

在此输入图像描述

您将遇到的问题是您的应用程序没有与运行测试时相同的命名空间. <AppName>.<ClassName>VS<AppName>Tests.<ClassName>

编辑:作为应用程序和测试运行的解决方案

我刚写了一段代码来解决<AppName>.<ClassName>vs <AppName>Tests.<ClassName>问题.我此时使用的解决方案(Xcode 6.1)是不填充ClassCoreData UI中的字段(如上所示),而是在代码中填写.

此代码将检测您是否作为App vs Tests运行,并使用正确的模块名称并更新managedObjectClassName.

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional...
    let modelURL = NSBundle.mainBundle().URLForResource("Streak", 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) ? "StreakTests" : "Streak"

    // 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
}()
Run Code Online (Sandbox Code Playgroud)


Oli*_*haw 5

我想我会得到类似的结果.我无法让我的测试工作

var newDept = NSEntityDescription.insertNewObjectForEntityForName("Department", inManagedObjectContext: moc) as Department
Run Code Online (Sandbox Code Playgroud)

但我可以通过以下方式运行测试:

let entity = NSEntityDescription.entityForName("Department", inManagedObjectContext: moc)
let department = Department(entity: entity!, insertIntoManagedObjectContext: moc)
Run Code Online (Sandbox Code Playgroud)

我的实体看起来像:

@objc(Department)
class Department: NSManagedObject {

    @NSManaged var department_description: String
    ...
}
Run Code Online (Sandbox Code Playgroud)