运行第二个单元测试时核心数据实体名称为零
Posted
技术标签:
【中文标题】运行第二个单元测试时核心数据实体名称为零【英文标题】:Core Data entity name is nil while running a second unit test 【发布时间】:2018-12-08 10:38:55 【问题描述】:我正在尝试为我的核心数据代码添加一些单元测试。但我总是有这个问题,第一个测试总是正确运行,但第二个测试崩溃,因为实体名称为零。
我也收到此错误:
Multiple NSEntityDescriptions claim the NSManagedObject subclass 'Gym.Exercise' so +entity is unable to disambiguate.
Failed to find a unique match for an NSEntityDescription to a managed object subclass
所以我的猜测是我在 tearDown().
中没有做正确的事情
override func setUp()
super.setUp()
coreDataStack = CoreDataStack(storeType: .inMemory)
context = coreDataStack.context
override func tearDown()
coreDataStack.reset()
context = nil
super.tearDown()
这是我的CoreDataStack
课程:
final class CoreDataStack
var storeType: StoreType!
public init(storeType: StoreType)
self.storeType = storeType
lazy var persistentContainer: NSPersistentContainer =
let container = NSPersistentContainer(name: "Gym")
container.loadPersistentStores description, error in
if let error = error
fatalError("Unresolved error \(error), \(error.localizedDescription)")
else
description.type = self.storeType.type
return container
()
public var context: NSManagedObjectContext
return persistentContainer.viewContext
public func reset()
guard let store = persistentContainer.persistentStoreCoordinator.persistentStores.first else fatalError("No store found")
guard let url = store.url else fatalError("No store URL found")
try! FileManager.default.removeItem(at: url)
NSPersistentStoreCoordinator.destroyStoreAtURL(url: url)
以及destroyStoreAtURL
的定义:
extension NSPersistentStoreCoordinator
public static func destroyStoreAtURL(url: URL)
do
let psc = self.init(managedObjectModel: NSManagedObjectModel())
try psc.destroyPersistentStore(at: url, ofType: NSSQLiteStoreType, options: nil)
catch let e
print("failed to destroy persistent store at \(url)", e)
我过去使用此代码进行单元测试并且它有效,不同之处在于过去我在编辑器中设置 NSManagedObject
类时使用了以下配置:
Module - Global namespace
Codegen - Class Definition
现在我使用:
Module - Current Product Module
Codegen - Manual/None
因为我想手动添加我的课程。
那么有人知道为什么现在的行为不同了吗?
edit - 我的 NSManagedObject 扩展助手(在尝试检索实体名称时,错误发生在 fetch() 方法的第一行):
extension Managed where Self: NSManagedObject
public static var entityName: String
return entity().name!
public static func fetch(in context: NSManagedObjectContext, configurationBlock: (NSFetchRequest<Self>) -> () = _ in ) -> [Self]
let request = NSFetchRequest<Self>(entityName: Self.entityName)
configurationBlock(request)
return try! context.fetch(request)
public static func count(in context: NSManagedObjectContext, configure: (NSFetchRequest<Self>) -> () = _ in ) -> Int
let request = NSFetchRequest<Self>(entityName: entityName)
configure(request)
return try! context.count(for: request)
public static func findOrFetch(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self?
guard let object = materializeObject(in: context, matching: predicate) else
return fetch(in: context) request in
request.predicate = predicate
request.returnsObjectsAsFaults = false
request.fetchLimit = 1
.first
return object
public static func materializeObject(in context: NSManagedObjectContext, matching predicate: NSPredicate) -> Self?
for object in context.registeredObjects where !object.isFault
guard let result = object as? Self, predicate.evaluate(with: result) else
continue
return result
return nil
public static func findOrCreate(in context: NSManagedObjectContext, matching predicate: NSPredicate, configure: (Self) -> ()) -> Self
guard let object = findOrFetch(in: context, matching: predicate) else
let newObject: Self = context.insertObject()
configure(newObject)
return newObject
return object
【问题讨论】:
请显示出错的代码。 @pbasdf: 完成,在 fetch(...) 方法内部发生错误,尝试检索实体名称时的第一行 考虑到该错误,首先想到的是您可能无意中在模型编辑器中定义了具有相同类的两个实体。您是否检查了所有实体定义以确保它们具有正确的类? @pbasdf:模型中只添加了一个实体,并且在代码中由我定义了一次。所以什么也没产生。 【参考方案1】:您应该尝试删除所有找到的 persistentStore 实例,而不是删除第一个。
尝试使用以下替换重置功能:
public func reset()
let stores = persistentContainer.persistentStoreCoordinator.persistentStores
guard !stores.isEmpty else
fatalError("No store found")
stores.forEach store in
guard let url = store.url else fatalError("No store URL found")
try! FileManager.default.removeItem(at: url)
NSPersistentStoreCoordinator.destroyStoreAtURL(url: url)
看看你是否还有问题。
【讨论】:
现在我收到以下错误:尝试获取请求时出现 NSSQLiteErrorDomain = 522。所以当在 fetch(...) 方法中调用“return try!context.fetch(request)”时。 而再次运行时,总是在加载持久化存储的时候报错,同样,522错误。以上是关于运行第二个单元测试时核心数据实体名称为零的主要内容,如果未能解决你的问题,请参考以下文章
带有 jacoco 插件的 SonarQube 覆盖百分比显示为零,但可以看到单元测试的数量
MockEJB - JUnit Mockito - 无法在第二个单元测试中重新绑定模拟 EJB