StoreType是否与NSBatchDeleteRequest

StoreType是否与NSBatchDeleteRequest

本文介绍了NSInMemoryStoreType是否与NSBatchDeleteRequest不兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在对与Core Data交互的层进行单元测试。它保存,删除和更新 Item 对象。但是,我尝试保存几个 Item s然后执行批量删除的测试始终失败。

I am currently unit testing a layer that interacts with Core Data. It saves, deletes, and updates an Item object. However, my test that attempts to save a couple of Items and then perform a batch deletion keeps failing.

这是 Item

extension Item {

    // MARK: - Properties

    @NSManaged public var date: NSDate

    @NSManaged public var isTaxable: Bool

    @NSManaged public var name: String

    @NSManaged public var price: NSDecimalNumber

    @NSManaged public var quantity: Double

    // MARK: - Fetch Requests

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Item> { return NSFetchRequest<Item>(entityName: "Item") }

    // MARK: - Validation

    // Manual validation for `Decimal` values is needed. A radar is still open, which is located at https://openradar.appspot.com/13677527.
    public override func validateValue(_ value: AutoreleasingUnsafeMutablePointer<AnyObject?>, forKey key: String) throws {
        if key == "price", let decimal = value.pointee as? Decimal { if decimal < Decimal(0.01) { throw NSError(domain: NSCocoaErrorDomain, code: 1620, userInfo: ["Item": self]) } }
        if key == "quantity", let double = value.pointee as? Double { if double == 0 { throw NSError(domain: NSCocoaErrorDomain, code: 1620, userInfo: ["Item": self]) } }
    }

}

这是与Core Data交互的对象, CoreDataStack

This is the object that interacts with Core Data, CoreDataStack:

internal class CoreDataStack {

    // MARK: - Properties

    private let modelName: String

    internal lazy var storeContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: self.modelName)
        container.loadPersistentStores { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }
        return container
    }()

    internal lazy var managedContext: NSManagedObjectContext = { return self.storeContainer.viewContext }()

    // MARK: - Initialization

    internal init(modelName: String = "Cart") { self.modelName = modelName }

    // MARK: - Saving

    internal func saveContext() throws {
        guard managedContext.hasChanges else { return }
        do { try managedContext.save() } catch let error as NSError { throw error }
    }

}

这是管理核心数据持久性的对象:

This is the object that manages persistence with Core Data:

internal final class ItemPersistenceService {

    // MARK: - Properties

    private let coreDataStack: CoreDataStack

    // MARK: - Initialization

    internal init(coreDataStack: CoreDataStack) {
        self.coreDataStack = coreDataStack
        print("init(coreDataStack:) - ItemPersistenceService")
    }

    // MARK: - Saving

    @discardableResult internal func saveItem(withInformation information: ItemInformation) throws -> Item {
        let item = Item(context: coreDataStack.managedContext)
        item.name = information.name
        item.quantity = information.quantity
        item.price = information.price as NSDecimalNumber
        item.date = information.date as NSDate
        item.isTaxable = information.isTaxable
        do {
            try coreDataStack.saveContext()
        } catch let error as NSError {
            throw error
        }
        return item
    }

    // MARK: - Deleting

    internal func delete(item: Item) throws {
        coreDataStack.managedContext.delete(item)
        do {
            try coreDataStack.saveContext()
        } catch let error as NSError {
            throw error
        }
    }

    internal func deleteAllItems() throws {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: Item.description())
        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
        do {
            try coreDataStack.managedContext.persistentStoreCoordinator?.execute(deleteRequest, with: coreDataStack.managedContext)
        } catch let error as NSError {
            throw error
        }
    }

     // MARK: - Fetching

    internal func itemsCount() throws -> Int {
        let fetchRequest = NSFetchRequest<NSNumber>(entityName: Item.description())
        fetchRequest.resultType = .countResultType
        do {
            let result = try coreDataStack.managedContext.fetch(fetchRequest)
            guard let count = result.first?.intValue else { fatalError("Invalid result") }
            return count
        } catch {
            throw error
        }
    }

}

这是<$我用于测试的c $ c> CoreDataStack 子类,其中包含一个内存中的存储:

This is the CoreDataStack subclass that I use for testing, which contains an in-memory store:

internal final class TestCoreDataStack: CoreDataStack {

    // MARK: - Initialization

    internal override init(modelName: String = "Cart") {
        super.init(modelName: modelName)
        let persistentStoreDescription = NSPersistentStoreDescription()
        persistentStoreDescription.type = NSInMemoryStoreType
        let container = NSPersistentContainer(name: modelName)
        container.persistentStoreDescriptions = [persistentStoreDescription]
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") }
            self.storeContainer = container
        }
    }

}

最后,这是不断失败的测试:

Finally, this is the test that keeps failing:

internal func test_ItemPersistenceService_Delete_All_Managed_Object_Context_Saved() {
    do {
        try service.saveItem(withInformation: information)
        try service.saveItem(withInformation: information)
    } catch { XCTFail("Expected `Item`") }
    expectation(forNotification: .NSManagedObjectContextDidSave, object: coreDataStack.managedContext) { (notification) in return true }
    do { try service.deleteAllItems() } catch { XCTFail("Expected deletion") }
    waitForExpectations(timeout: 2.0) { error in XCTAssertNil(error, "Expected save to occur") }
}

问题

是NSInMemo ryStoreType与NSBatchDeleteRequest不兼容吗?

Is NSInMemoryStoreType incompatible with NSBatchDeleteRequest?

如果不是,那我做错了什么导致我的测试反复失败?

If not, then what am I doing incorrectly that is causing my test to fail repeatedly?

推荐答案

您始终可以创建SQLite类型的持久存储并将其存储在 / dev / null 中。这是在快速的 XCTest 类上执行此操作的代码:

You can always create a persistent store of type SQLite and store it at /dev/null. Here's the code to do it on a swift XCTest class:

var container: NSPersistentContainer!

override func setUp() {
    super.setUp()
    container = NSPersistentContainer(name: "ModelName")
    container.persistentStoreDescriptions[0].url = URL(fileURLWithPath: "/dev/null")
    container.loadPersistentStores { (description, error) in
        XCTAssertNil(error)
    }
}

这篇关于NSInMemoryStoreType是否与NSBatchDeleteRequest不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 23:50
查看更多