Reputation:
I am writing XCTest cases but I am stuck at one place. I have a Class Car in my main target which is subclass of NSManagedObject. I am creating mock which will have array of objects of Car class. But whenever I use setter for elements of Car it get crash.
In Main Target
class Car: NSManagedObject {
@NSManaged var name: String
}
In Test Target
class CarTests: XCTestCase {
func testCar() {
let car = getMyCar()
// Some asserts here
}
func getMyCar() -> Car {
let car: Car = Car.Init()
car.name = "Ferrari"
return car
}
}
Here it crash when I set car name. Any Idea how I can create mock data of car object?
error - failed: caught "NSInvalidArgumentException", "-[MyProject.Car setName:]: unrecognized selector sent to instance 0x310434347f200"
Upvotes: 7
Views: 2746
Reputation: 1018
You can completely override the NSManagedObject
subclass property getters in a new stub subclass in your test target. self.init()
works fine.
class StubCar: Car {
convenience init(name: String = "") {
self.init()
self.stubbedName = name
}
var stubbedName: String = ""
override var name: String {
set {}
get {
return stubbedName
}
}
}
Now usage in a test is simply let stubCar = StubCar()
and there are no CoreData related crashes when production code accesses properties and you don't need to setup a full in memory CoreData stack at all. Override the setter as well if you need to. This assumes you have your data layer properly abstracted away so you can just inject these models where they're needed and write tests as such.
Upvotes: 8
Reputation: 733
This is due to Car being an NSManagedObject subclass which means it has to be initialized with its designated initializer: initWithEntity:insertIntoManagedObjectContext:
.
In this small article you can find more info on working with NSMangedObjects and XCTests: https://www.andrewcbancroft.com/2015/01/13/unit-testing-model-layer-core-data-swift/
Upvotes: 5