thisIsTheFoxe
thisIsTheFoxe

Reputation: 1713

CoreData error: Must supply a fetch request during initialization

I have the following code setup for all my CoreData UnitTests (where context is my viewContext and Item is a CoreData model):

override func setUpWithError() throws {
    let deleteReq = NSBatchDeleteRequest(fetchRequest: Item.fetchRequest())
    try context.execute(deleteReq)
}

Now, I'm getting this error when declaring deleteReq:

Must supply a fetch request during initialization (NSInvalidArgumentException)

I set-up my controller like this:

let testController = PersistenceController(inMemory: true)

// #### - ####

init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: "AppName")
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
    }
    
    container.viewContext.automaticallyMergesChangesFromParent = true
    container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        // [...]
        return
    })
}

Am I doing something wrong?

Upvotes: 0

Views: 467

Answers (2)

thisIsTheFoxe
thisIsTheFoxe

Reputation: 1713

Ok, I have an easy solution, tho not ideal:

var testController = PersistenceController(inMemory: true)

override func setUpWithError() throws {
    testController = PersistenceController(inMemory: true)
}

As I said, not ideal.. But it works as expected. New (empty) Controller / Container for each test.

Not entirely sure what causes the error. Maybe there's some problems with deleting stuff from "/dev/null".

Upvotes: 1

julltron
julltron

Reputation: 27

ETA: This actually didn't help 🤦🏻‍♂️ I was conflating two different problems and this answer solved the other one. Sorry. If you find an answer to your question, lmk. I'll do the same.


I was also having this problem today - almost exactly the same setup, so hopefully what worked for me will help you.

Turns out it had to do with the way I was trying to get my context into the tests, which made the error message pretty misleading. I added a property for the main context into my dataController and referenced that in my test, and it's working now.

In the app, DataController.swift (I also had to add this file to the test target):

class DataController: ObservableObject {
    let container: NSPersistentCloudKitContainer
    let moc: NSManagedObjectContext

    init(inMemory: Bool = false) {
        container = NSPersistentCloudKitContainer(name: "Main") // or "AppName"
    
        if inMemory {
            container.persistentStoreDescriptions.first?.url = URL(fileURLWithPath: "/dev/null")
        }
    
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error {
                fatalError("Fatal error loading store: \(error.localizedDescription)")
            }
        }
    
        moc = container.viewContext
    }

    ...

    func deleteAll() {
        let fetchRequest: NSFetchRequest<NSFetchRequestResult> = EntityName.fetchRequest()
        let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        _ = try? container.viewContext.execute(batchDeleteRequestSteps)
    }
}

In my test:

class SomeTests: XCTestCase {

    var dataController = DataController()

    override func setUpWithError() throws {
        let context: NSManagedObjectContext = dataController.moc
        dataController.deleteAll()
        let entityTestObj = EntityName(context: context)
        
        // some setup stuff here

        dataController.save()
    }

    // ... actual tests here
}

Upvotes: 0

Related Questions