zono
zono

Reputation: 8584

Swift CoreData UnitTest: How to avoid EXC_BREAKPOINT

This would be common problem in CoreData unit testing using swift. EXC_BREAKPOINT exception happens due to swift's namespace differences between normal module and test module. I'm still struggling against this issue even though some solutions are introduced.

What I did and my problem is here.

  1. Create new project using the single application template with core data using check option.
  2. Run unit tests. No errors occurred.
  3. Add CoreDataSampleTest target to Appdelegate.swift.
  4. Change testExample() in CoreDataSampleTests.swift as followings.
func testExample() {
    let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
}
  1. Run unit tests. EXC_BREAKPOINT occurred.
  2. Change managedObjectModel() in AppDelegate.swift as following Swift cannot test core data in Xcode tests?.
lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional...
    let modelURL = NSBundle.mainBundle().URLForResource("CoreDataSample", withExtension: "momd")!
    let managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)!

    // Check if we are running as test or not
    let environment = NSProcessInfo.processInfo().environment as [String : AnyObject]
    let isTest = (environment["XCInjectBundle"] as? String)?.pathExtension == "xctest"

    // Create the module name
    let moduleName = (isTest) ? "CoreDataSampleTests" : "CoreDataSample"

    // Create a new managed object model with updated entity class names
    var newEntities = [] as [NSEntityDescription]
    for (_, entity) in enumerate(managedObjectModel.entities) {
        let newEntity = entity.copy() as NSEntityDescription
        newEntity.managedObjectClassName = "\(moduleName).\(entity.name)"
        newEntities.append(newEntity)
    }
    let newManagedObjectModel = NSManagedObjectModel()
    newManagedObjectModel.entities = newEntities

    return newManagedObjectModel
}()
  1. Run unit tests. EXC_BREAKPOINT occurred again.

What I want to know are two things.

  1. How to avoid EXC_BREAKPOINT exception. Test methods seem to work normally but EXC_BREAKPOINT exception temporary stop the process at every test methods. I have to resume it every time. It very hard to run the test methods.

  2. If I cannot avoid EXC_BREAKPOINT, I want to ignore the EXC_BREAKPOINT exception when executing unit tests.

Any help or suggestion would be helpful for me.

Thanks,

FYI:

Swift cannot test core data in Xcode tests?.

Edit:

XCode Version is 6.2

Upvotes: 1

Views: 1504

Answers (1)

Ali Beadle
Ali Beadle

Reputation: 4526

As Wolfgang said I think the Jesse Squires solution works (it does for me) but there are several steps:

  • Optional: Move your Core Data into a separate module (I used a Framework as Xcode 6.2 still seems not to like Swift static libraries) - this tip curtesy of Jessie Squires,

(This is not necessary but will help keep things tidy as the following steps involve making a lot of things public and that will spread through your whole project if you do not separate it out.)

  • add @objc(ClassName) to all your NSManagedObject classes,
  • make all your NSManagedObject classes and all their contained properties public,

You should end up with entities that look like this:

import Foundation
import CoreData

@objc(ClassName)
public class ClassName: NSManagedObject {
    @NSManaged public var property: Type        
}
  • make the Entity Class name for all your entities in your model a simple reference to the class (e.g. ClassName not a AppName.ClassName).
  • make public all classes, methods, properties etc. that are in the same module as Core Data and that you want to unit test,
  • remove all your classes from the test target (i.e. untick the test target in 'Target Membership' for each of them), but leave the data model in the test target,
  • import your app into your test class(es) (e.g. add import AppName to the test class source).

There is an alternative approach in the SO answer here that also works.

Edit 1: Added note about alternative.

Edit 2: Passed on tip to move Core Data into a separate module.

Upvotes: 3

Related Questions