swift - 单元测试 CoreData (+ MagicalRecord) 模型触发器 EXC_BAD_ACCESS
swift - Unit test CoreData (+ MagicalRecord) model triggers EXC_BAD_ACCESS
我需要对我的一些方法进行单元测试 (XCTest
),其中包括对 CoreData 模型的引用。
以下行正确执行:
var airport: AnyObject! = Airport.MR_createEntity()
(lldb) po airport <Airport: 0x7fcf54216940> (entity: Airport; id: 0x7fcf54216a20 <x-coredata:///Airport/t1D3D08DA-70F9-4DA0-9487-BD6047EE93692> ; data: {
open = nil;
shortName = nil;
visible = nil; })
而以下行触发 EXC_BAD_ACCESS
:
var airport2: Airport = Airport.MR_createEntity() as! Airport
(lldb) po airport2
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0).
The process has been returned to the state before expression evaluation.
我的主要目标没有出现此错误的迹象。配置是:两个目标中的模型对象,class 以 @objc(MyModel)
为前缀,我的 xcdatamodel
中的 class' 模型中没有命名空间
知道这里发生了什么吗?
有两种方法可以使您的 Swift 应用程序 类 可用于测试目标:
制作您的应用程序 类 public – 这包括您要测试的每个变量、常量和函数
将您的应用程序 Swift 文件添加到您的测试目标。这很简单。
是的,所以我终于弄清了这个问题,但它并不漂亮。这个问题实际上有一个 radar,因为它似乎是 Swift 编译器无法识别测试目标中的 ManagedObject 转换的错误。所以加入你的声音
从定义如下的实体开始:
@objc(Member)
class Member: NSManagedObject {
@NSManaged var name: String
}
我写了一个简单的测试 class,其中我用 3 种不同的方式创建了一个 MO:
前两个失败:
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
}
然后就成功了
func testManualMOCreation() {
let ent = NSEntityDescription.entityForName("Member", inManagedObjectContext: context)!
let m3 = Member(entity: ent, insertIntoManagedObjectContext: context)
XCTAssertNotNil(m3, "Failed to create object")
}
这意味着现在您有两个选择。在 Objective-C 中编写测试;或者创建一个实用程序方法,使用我上面显示的方法将测试对象插入到上下文中。
关于此行为有一个很好的 post here
我最终使用了 NSManagedObjectContext 扩展,在 Swift 测试中明确使用:
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)
}
}
它可以像这样使用:
func testConvenienceCreation() {
let m4 = context.insertTestEntity(Member)
XCTAssertNotNil(m4, "Failed to create object")
}
更多关于这种方法的阅读here
我需要对我的一些方法进行单元测试 (XCTest
),其中包括对 CoreData 模型的引用。
以下行正确执行:
var airport: AnyObject! = Airport.MR_createEntity()
(lldb) po airport <Airport: 0x7fcf54216940> (entity: Airport; id: 0x7fcf54216a20 <x-coredata:///Airport/t1D3D08DA-70F9-4DA0-9487-BD6047EE93692> ; data: {
open = nil;
shortName = nil;
visible = nil; })
而以下行触发 EXC_BAD_ACCESS
:
var airport2: Airport = Airport.MR_createEntity() as! Airport
(lldb) po airport2
error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x0).
The process has been returned to the state before expression evaluation.
我的主要目标没有出现此错误的迹象。配置是:两个目标中的模型对象,class 以 @objc(MyModel)
为前缀,我的 xcdatamodel
知道这里发生了什么吗?
有两种方法可以使您的 Swift 应用程序 类 可用于测试目标:
制作您的应用程序 类 public – 这包括您要测试的每个变量、常量和函数
将您的应用程序 Swift 文件添加到您的测试目标。这很简单。
是的,所以我终于弄清了这个问题,但它并不漂亮。这个问题实际上有一个 radar,因为它似乎是 Swift 编译器无法识别测试目标中的 ManagedObject 转换的错误。所以加入你的声音
从定义如下的实体开始:
@objc(Member)
class Member: NSManagedObject {
@NSManaged var name: String
}
我写了一个简单的测试 class,其中我用 3 种不同的方式创建了一个 MO:
前两个失败:
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
}
然后就成功了
func testManualMOCreation() {
let ent = NSEntityDescription.entityForName("Member", inManagedObjectContext: context)!
let m3 = Member(entity: ent, insertIntoManagedObjectContext: context)
XCTAssertNotNil(m3, "Failed to create object")
}
这意味着现在您有两个选择。在 Objective-C 中编写测试;或者创建一个实用程序方法,使用我上面显示的方法将测试对象插入到上下文中。
关于此行为有一个很好的 post here
我最终使用了 NSManagedObjectContext 扩展,在 Swift 测试中明确使用:
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)
}
}
它可以像这样使用:
func testConvenienceCreation() {
let m4 = context.insertTestEntity(Member)
XCTAssertNotNil(m4, "Failed to create object")
}
更多关于这种方法的阅读here