Unit Testing CoreData Tip: The Singleton

It’s been a while since I was deep into CoreData, but here I am again. And this time, I’m writing proper unit tests.

Things were going pretty well – I had about 50 test cases with a few related asserts in each – until I started messing with saving, and fetching tests. I ran into some odd behavior where sometimes a particular test would pass, other times fail with different results in one assertion. All I was doing was creating a managed object, setting a relationship, saving, and reading back to check for proper order. Pretty trivial stuff.

I looked deeper.

If I ran just that one test case by itself, it would always pass. If I ran “All Tests”, it would always fail. Sometimes I would get several fetched objects when only one was expected. Sometimes those would be in different orders.

As I dug deeper, I attempted to reset my context on each test case

No luck.

To this point, my managedObjectContext has been a singleton – to follow the pattern of the rest of the appellation. I had a hunch the problem might be there – especially if multiple tests are running (concurrently, even?).

I tried creating a separate for-testing-only manager that creates a new stack each time so I could hopefully avoid these apparent concurrency issues.

That seems to do the trick, though I would have preferred sticking with the singleton. Don’t use CoreData stack singletons. Turns out @orta suggests the same [tweet] [blog post].

Quiet NSLog() in Release Builds

On the heels of the previous post, here’s a little snippit I picked up from Marek Bell to quiet NSLog() output in release builds.

Add this to your {MyApp}-prefix.pch file

#ifndef __OPTIMIZE__
#    define NSLog(…) NSLog(__VA_ARGS__)
#    define NSLog(…) {}

The reasoning behind using __OPTIMIZE__ is that it’s set only on release builds of your app, not in debug versions. It’s very simple and allows you to use NSLog() instead of having to come up with your own version.