Reputation: 1713
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
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
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