My app uses CoreData. One of the entities is
final class ViewItem: NSManagedObject {
// …
}
During unit tests, I am trying to execute the following fetch request:
let viewItemFetchRequest = NSFetchRequest<ViewItem>(entityName: "ViewItem")
as
viewContext.performAndWait {
do {
let fetchedViewItems = try viewContext.fetch(viewItemsFetchRequest)
let viewItems = Set(fetchedViewItems)
// …
}
Although the code executes correctly during normal operation, during unit tests it crashes.
When I set a breakpoint behind the try
instruction, this breakpoint is reached, i.e. the fetch does not throw.
However I get a fatal error when I want to access fetchedViewItems
, either by Set(fetchedViewItems)
or with
(lldb) po fetchedViewItems
Fatal error: NSArray element failed to match the Swift Array Element type
Expected ViewItem but found ViewItem
2022-06-07 10:31:30.245019+0200 ShopEasy[42069:1864673] Fatal error: NSArray element failed to match the Swift Array Element type
Expected ViewItem but found ViewItem
1 value
Here is the relevant part of the stack frame:
What could be the reason and how could I fix the problem?
PS: I found some posts related to this error, this, this and this one, but in none of them is reported Expected <some type> but found <some type>
.
EDIT:
To investigate the situation, I modified the code as follows:
viewContext.performAndWait {
do {
let fetchedViewItems: [ViewItem] = try viewContext.fetch(viewItemsFetchRequest)
let fetchedObjects: [AnyObject] = try viewContext.fetch(viewItemsFetchRequest)
let viewItems = Set(fetchedViewItems)
// …
}
and set a breakpoint at let viewItems = Set(fetchedViewItems)
, the instruction that crashes.
This is the situation when the breakpoint is reached:
Printing the description of fetchedObjects in the Variables View of the Debug area gives
Printing description of fetchedObjects:
▿ 1 element
▿ 0 : <ShopEasy.ViewItem: 0x10b3147c0> (entity: ViewItem; id: 0x10b822540 <x-coredata:///ViewItem/t51E2E772-5F7C-43E4-BBC6-68DC139F1BE02>; data: {
fixedAtTopAt = nil;
…
and in the console
(lldb) po fetchedObjects
▿ 1 element
▿ 0 : <ShopEasy.ViewItem: 0x10b3147c0> (entity: ViewItem; id: 0x10b822540 <x-coredata:///ViewItem/t51E2E772-5F7C-43E4-BBC6-68DC139F1BE02>; data: {
fixedAtTopAt = nil;
…
However, printing the description of fetchedViewItems in the Variables View of the Debug area gives
Printing description of fetchedViewItems:
([ShopEasyTests.ViewItem]) fetchedViewItems = 1 value {
[0] = 0x000000010b3147c0
}
but in the console
(lldb) po fetchedViewItems
Fatal error: NSArray element failed to match the Swift Array Element type
Expected ViewItem but found ViewItem
2022-06-08 08:54:02.359228+0200 ShopEasy[51124:2241262] Fatal error: NSArray element failed to match the Swift Array Element type
Expected ViewItem but found ViewItem
1 value
This seems to be some conflict between the apps namespace (ShopEasy.ViewItem) and the unit tests namespace (ShopEasyTests.ViewItem).
2
Answers
I could reproduce your error in a sample project where the managed object class definition file was added both to the application target and the unit tests target. This also gave some console warnings when running tests about the class being implemented in two places.
Is this what is happening in your case?
The code should only be present in your app target, and you should use
@testable import ShopEasy
to access app code in your unit tests.I had the same error message, in my case I was missing:
@objc(ViewItem)
on top of theNSManagedObject
class definition.I only had:
instead of: