Тестирование операций CoreData CRUD и отсутствие уведомления NSManagedObjectDidSave - PullRequest
0 голосов
/ 22 сентября 2019

У меня есть метод вставки какого-либо объекта в хранилище Core Data.

func insert(_ e: Entity, completion: @escaping (Result<Entity, Error>) -> Void) {

        storage.persistentContainer.performBackgroundTask { [weak self] context in
            guard let self = self else { return }

    }  
}

У меня также есть такой тестовый пример, и только последнее изменение changeExpectation завершается неудачно, так как я не получаю это уведомление.

func test_whenMovieSaved_shouldBeRetrivable() {

        // given
        let dao = MoviesDao(storage: storage)
        let movie = Movie(id: 1, title: "Test Title", posterPath: nil, overview: "Test Details", releaseDate: nil)

        let insertExpectation = self.expectation(description: "Should insert entity.")
        let loadExpectation = self.expectation(description: "Should load entity.")
        let changeExpectation = self.expectation(forNotification: .NSManagedObjectContextDidSave, object: storage.persistentContainer.viewContext, handler: nil)
        // when
        dao.insert(movie) { (result) in

            guard let e = try? result.get() else {
                XCTFail("Should get valid entity back.")
                return
            }

            XCTAssertEqual(movie, e)
            insertExpectation.fulfill()

            dao.load(id: "\(movie.id)") { result in

                guard let e = try? result.get() else {
                    XCTFail("Should load valid entity back.")
                    return
                }

                XCTAssertEqual(movie, e)
                loadExpectation.fulfill()
            }
        }

        // then
        wait(for: [insertExpectation, loadExpectation], timeout: 0.2)
        wait(for: [changeExpectation], timeout: 2)
    }

Я даже пытался добавить что-то подобное, но это не заставило уведомление отправлять self.storage.saveContext (context)

            NSManagedObjectContext.mergeChanges(fromRemoteContextSave: [NSInsertedObjectsKey: insertedObjectIds], into: [self.storage.persistentContainer.viewContext])
            completion(.success(e))

У меня также есть что-то подобноепри создании persistentCoordinator

 container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
        container.viewContext.undoManager = nil
        container.viewContext.shouldDeleteInaccessibleFaults = true

        container.viewContext.automaticallyMergesChangesFromParent = true

1 Ответ

0 голосов
/ 22 сентября 2019

Я думаю, что наконец нашел решение этой проблемы.Это было в методе stack.saveContext (context), так как я использую executeBackgroundTask {context в

, который требует не только вызова фонового context.save (), но и вызова метода viewContext.save ().

В моем CoreDataStack теперь есть такие методы

  func saveContextAsync(_ context: NSManagedObjectContext) {
        guard context != mainContext else {
            saveContext()
            return
        }


        context.perform {
            do {
                try context.save()
            } catch let error as NSError {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }

            self.saveContextAsync(self.mainContext)
        }
    }

    func saveContext(_ context: NSManagedObjectContext) {
        guard context != mainContext else {
            saveContext()
            return
        }

        context.performAndWait {
            do {
                try context.save()
            } catch let error as NSError {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }

            self.saveContext(self.mainContext)
        }
    }

func saveContextAsync() {
        let context = mainContext

        // Save all the changes just made and reset the context to free the cache.
        context.perform {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
            // Reset the context to clean up the cache and low the memory footprint.
            context.reset()
        }
    }

    func saveContext() {
        let context = mainContext

        // Save all the changes just made and reset the context to free the cache.
        context.performAndWait {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
            // Reset the context to clean up the cache and low the memory footprint.
            context.reset()
        }
    }
...