Realm is an increasingly popular replacement for Core Data or raw SQLite on iOS (and Android). It supports Swift quite well but I’ve had some trouble getting my test setup right, so here’s what’s working for me. My project is using Swift and is configured to run Tests using the XCTest Framework, so everything’s pretty vanilla. As always, I’m using Cocoapods for depedency management. If you’re using carthage stuff might be different.

First of all, make sure your model files really just belong to your apps target and are not included in any test target (Right side tab, target membership in Xcode). What you want to do next is to make sure that your Podfile also lists Realm as a depedency for your test target, like this:

platform :ios, '8.0'
use_frameworks!

target 'App' do
   pod 'PMKVObserver'
   pod 'RealmSwift'
   pod 'SnapKit'
end

target 'AppTest' do
   pod 'RealmSwift'
   pod 'PMKVObserver'
   pod 'SnapKit'
end

target 'AppUITests' do

end

The next step is crucial and contains a TIL for me: I didn’t know about the @testable statement that can prepend import statements in test targets. This statement overrides the visibility of the packages contained in the module you’re about to export so that your test can pretty much see everything inside. In your XCTestCase file, just import your App module.

@testable import App

That’s it, after doing a pod install you can run your tests.

You can configure which tests get run when you select Product -> Run (or Command-U) by editing the Scheme of your App. The Test section in ‘Edit Schemes’ has a tab named ‘Info’. You can select the tests you’d like to run there.

In-Memory database for testing

Of course, good tests are reproducible and independent from their environment so it’s a pretty good idea to use different realms for testing and the real thing. I don’t like preprocessor macros and they wouldn’t work for us anyway, so here’s what I came up with.

class RealmProvider {
    class func realm() -> Realm {
        if let _ = NSClassFromString("XCTest") {
            return try! Realm(configuration: Realm.Configuration(path: nil, inMemoryIdentifier: "test", encryptionKey: nil, readOnly: false, schemaVersion: 0, migrationBlock: nil, objectTypes: nil))
        } else {
            return try! Realm();
   
        }
    }
}

Just use RealmProvider.realm() instead of try! Realm() and your app uses the in-memory database automatically. Also, if you’re looking for a setup method in your tests that clears your data, here you go.

override func setUp() {
    super.setUp()
    let realm = RealmProvider.realm()
    try! realm.write { () -> Void in
        realm.deleteAll()
    }
}

Happy Testing!