Unit testing with Core Data can be complicated. We want to reduce any dependencies in order to isolate the class under test. But Core Data itself is a big dependency. Graham Lee wrote a couple blog posts, several years ago on patterns for testing Core Data applications. He describes two patterns for isolating the the class under test. While Graham prefers to remove the Core Data dependency entirely, I’ve tended to use his second pattern by creating an in-memory Core Data stack that I build up and tear down with each test. I’ve done this for years using Objective-C; but now that Swift has come on the scene, I’ve had to adapt the process somewhat; and I’ll describe that here.
Application test example
We’ll start out by constructing a prototypical Employee/Manager model in a sample app. I’ve called the product (and module) name “Zoom”. This is important to know because we’ll need to prepend out
NSManagedObject model class names in the model editor with the module name. Because of what I regard as an Xcode 6 bug, you should not prefix the class names in the model editor until after you’ve generated the class files assuming you want Xcode to do that step for you. If you namespace the class names beforehand, then the
NSManagedObject subclass generation function in Xcode 6 won’t work properly.
With that in mind, create two entities: Boss and Employee. Give the
Boss entity, attributes of
firstName (String) and
lastName (String). Give the
Employee entity, attributes of
salary (Integer 16), and
Configure the relationships between
Employee. That should be obvious
Employee is To-many and then the reciprocal to keep Core Data happy.
Remember to set the Class field in the Entity inspector; but leave off the namespace if you’re first generating the
NSManagedObject subclasses. Your generated
Employee class should look like this:
Boss class should look like this:
When generating the subclasses for your model entities, remember to add the files to both the main target and the unit test target. The same goes for the model file itself. Now that we’ve set up the
NSManagedObject subclasses for our Core Data entities, we can namespace the classes in the model editor:
The Core Data stack
In my main application, I’ll just use the templated Core Data stack. It works as a starting point and it also can serve as the in-memory stack for our unit tests. To simplify testing of classes that use Core Data, I start with a base class that sets up and tears down our in-memory stack. We’ll call that class
Example test class
We’ll derive our test classes from this base class. For example, to test our
Boss class, we could begin with a test case class that derives from
Creating an in-memory store doesn’t completely eliminate the Core Data dependency; but it reduces the pre-test assumptions considerably and makes for more controlled testing in Core Data applications.
Lee, Graham. (6 September, 2009) Unit testing Core Data-driven apps. Retrieved Septeber 28, 2014, from http://iamleeg.blogspot.com/2009/09/unit-testing-core-data-driven-apps.html ↩
Lee, Graham. (10 January, 2010) Unit testing Core Data-drive apps, fit the second. Retrieved September 28, 2014, from http://iamleeg.blogspot.com/2010/01/unit-testing-core-data-driven-apps-fit.html ↩