NSManagedObject 子类模拟

NSManagedObject subclass mocking

我正在编写 XCTest 案例,但我被困在一个地方。 我的主要目标中有一辆 Class 汽车,它是 NSManagedObject 的子 class。我正在创建模拟,它将包含 Car class 的对象数组。但是每当我对 Car 的元素使用 setter 时,它就会崩溃。

在主要目标中

class Car: NSManagedObject {

    @NSManaged var name: String

}

在测试目标中

class CarTests: XCTestCase {



    func testCar() {

        let car = getMyCar()
        // Some asserts here

    }

    func getMyCar() -> Car {
        let car: Car = Car.Init()
        car.name = "Ferrari"

        return car
    }

}

此处设置车名时崩溃。知道如何创建汽车对象的模拟数据吗?

错误 - 失败:捕获 "NSInvalidArgumentException",“-[MyProject.Car setName:]:无法识别的选择器发送到实例 0x310434347f200”

这是因为 Car 是 NSManagedObject 的子类,这意味着它必须使用其指定的初始化程序进行初始化:initWithEntity:insertIntoManagedObjectContext:

在这篇小文章中,您可以找到有关使用 NSMangedObjects 和 XCTests 的更多信息: https://www.andrewcbancroft.com/2015/01/13/unit-testing-model-layer-core-data-swift/

您可以在测试目标的新存根子类中完全覆盖 NSManagedObject 子类 属性 getter。 self.init() 工作正常。

class StubCar: Car {
    convenience init(name: String = "") {
        self.init()
        self.stubbedName = name
    }

    var stubbedName: String = ""
    override var name: String {
        set {}
        get {
            return stubbedName
        }
    }
}

现在在测试中的使用很简单 let stubCar = StubCar() 并且在生产代码访问属性时没有与 CoreData 相关的崩溃,您根本不需要在内存中设置完整的 CoreData 堆栈。如果需要,也可以覆盖 setter 。这假设您已正确抽象出数据层,因此您可以在需要的地方注入这些模型并编写测试。