【问题标题】:Create CoreData object in tests with a simple init使用简单的 init 在测试中创建 CoreData 对象
【发布时间】:2019-04-04 12:56:01
【问题描述】:

我有一组NSManagedObject 子类供ClassToBeTested 使用。

ClassToBeTested 仅对 NSManagedObject 子类的几个属性进行操作,不需要关系或整个 CoreData 堆栈。

我可以通过以常规方式创建它们以某种方式在测试中使用相同的对象吗:

        let template = CoreDataClass()
        template.name = randomString(length: 40) // This fails!
        templates.append(template)

目前它失败并出现错误:

失败:捕获“NSInvalidArgumentException”,“-[CoreDataClass setTemplate_name:]: 无法识别的选择器发送到实例 0x600000af4c40"

【问题讨论】:

    标签: ios swift xcode testing core-data


    【解决方案1】:

    虽然我在尝试这样做时遇到了不同的错误(没有调用指定的初始化程序),但无论哪种情况,您的问题的答案都是:不,您不能这样做。 p>

    但是现在有了 NSPersistentContainer,很容易使用单例内存中的核心数据堆栈进行此类测试。将您的数据模型包含在您的测试包中,然后将其放入您的测试的全局范围内:

    var sharedTestContext: NSManagedObjectContext = {
        // Swift is smart enough to execute this only once.
        let container = NSPersistentContainer(name: "<YourDataModelName>")
        let description = NSPersistentStoreDescription()
        description.type = NSInMemoryStoreType
        container.persistentStoreDescriptions = [description]
        container.loadPersistentStores { (description, error) in
            if let error = error {
                fatalError("Failed to load store for test: \(error)")
            }
        }
        return container.newBackgroundContext()
    }()
    

    并定义一个特殊的托管对象初始化器用于测试,如下所示:

    /**
     Initializes a managed object for testing
    
     - important:  This assumes your managed object subclass name is the same
     as its entity name.
     */
    public extension NSManagedObject {
        convenience init(testContext: NSManagedObjectContext?) {
            let context = testContext ?? sharedTestContext
            /*  The following contraption is necessary to avoid warning:
             "Multiple NSEntityDescriptions claim the NSManagedObject subclass"
             For explanation see:
             https://stackoverflow.com/questions/51851485/multiple-nsentitydescriptions-claim-nsmanagedobject-subclass */
            let name = String(describing: type(of: self))
            let entity = NSEntityDescription.entity(forEntityName: name, in: context)!
            self.init(entity: entity, insertInto: context)
        }
    }
    

    现在你可以这样创建你的测试对象了:

    let template = CoreDataClass(testContext: nil)
    

    【讨论】:

      猜你喜欢
      • 2010-10-17
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      • 2010-12-16
      相关资源
      最近更新 更多