How to give unit tests access to Core Data models

2019-08-01 10:31发布

Let's say I've made Core Data models in my project. I have other classes with methods that take in these models and perform some function based on their properties. How do I unit test those classes?

With normal Swift files I select them in Xcode and tick a box which makes any classes defined in those files visible to the unit test part of the project. My question is essentially, how do I make my Core Data models also visible to the tests?

Note that I don't want to perform any operations on the Core Data stack, I just want to be able to create an instance of a model and pass it into a method.

2条回答
家丑人穷心不美
2楼-- · 2019-08-01 10:59

Since CoreData uses Managed Objects, any subclass of NSManagedObject is functionally worthless unless attached to a context.

One trick for testing is to create an NSManagedObjectContext in memory and create objects test using that context. Outlined Here

Here's the code for creating the context in memory:

func setUpInMemoryManagedObjectContext() -> NSManagedObjectContext {
    let managedObjectModel = NSManagedObjectModel.mergedModelFromBundles([NSBundle.mainBundle()])!

    let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)

    do {
        try persistentStoreCoordinator.addPersistentStoreWithType(NSInMemoryStoreType, configuration: nil, URL: nil, options: nil)
    } catch {
        print("Adding in-memory persistent store failed")
    }

    let managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = persistentStoreCoordinator

    return managedObjectContext
}
查看更多
冷血范
3楼-- · 2019-08-01 11:02

Update: The accessor implementations are generated at runtime, but they are not usable if the model object is not associated with a NSManagedObjectContext. So PEEJWEEJ's answer is the way to go.

If I am not mistaken, the Objective-C classes for your entities (in particular e.g. their property accessors) are generated at runtime, when they are used. So I would expect that you'd need to call NSManagedObjects initializer with the appropriate NSEntityDescription:

NSManagedObject(entity: entityDescription, insertInto: nil)

You can get the appropriate entity descriptions by loading your object model with NSManagedObjectModel and using e.g. that object's entitiesByName property.

If you use custom code for your NSManagedObject subclasses (e.g. generated with mogenerator), I would assume the same process would need to apply - make the generated code visible to your tests and use the MyModelClass(entity: entityDescription, insertInto: nil) initializer.

查看更多
登录 后发表回答