在Swift单元测试中向下转换NSManagedObjects时的命名空间问题

时间:2015-06-10 19:54:09

标签: ios swift unit-testing core-data

尝试在我的(Swift)单元测试中将获取的NSManagedObject向下转换为正确的子类StoryPhotoTrack时,我收到运行时错误:Could not cast value of type 'StoryPhotoTrack_StoryPhotoTrack_' (0x7fbda4734490) to 'StoryPhotoTrack' (0x11edd1b08).

这是我的失败/崩溃测试:

func testFetchingStoryWithCastingInvolved() {
    let story : StoryPhotoTrack? = storyFetcher.fetchAnyStoryPhotoTrack()
    XCTAssertNotNil(story, "should be a story") // works
    let definitlyAStory : StoryPhotoTrack = story! // works
    let object : NSManagedObject = story as NSManagedObject! // works
    println(NSStringFromClass(definitlyAStory.dynamicType)) // prints 'StoryPhotoTrack_StoryPhotoTrack_'
    let downCastedStory : StoryPhotoTrack = object as! StoryPhotoTrack // -> error: "Could not cast..."
    XCTAssertNotNil(downCastedStory, "should still be a story")
}

// StoryFetcher.swift
    func fetchAnyStoryPhotoTrackVia_ObjectiveC_Fetcher() -> StoryPhotoTrack? {
        let object = StoryPhotoTrack.fetchAnyStoryPhotoTrackInContext(moc)
        return object as StoryPhotoTrack?
    }

实际提取在Objective-C中完成:

// StoryPhotoTrack+Fetching.m
+ (StoryPhotoTrack *)fetchAnyStoryPhotoTrackInContext:(NSManagedObjectContext *)moc
{
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StoryPhotoTrack"];
    NSArray *storyTracks = [moc executeFetchRequest:request error:nil];
    return (StoryPhotoTrack *)[storyTracks lastObject];
}

我认为,它与Swift的命名空间有关。好像我的StoryPhotoTrack类实际上被称为StoryPhotoTrack_StoryPhotoTrack_

我尝试使用projectName-prefixes重命名我的核心数据实体的类名(如建议的here),但这没有帮助。我尝试了我的主目标模块名称和我的测试目标模块名称,但没有一个工作。 setting class prefix in core data model my testbundle module name

我做错了什么?

编辑:似乎我忽略了像How to test Core Data properly in Swift这样的问题,所以看来,这个问题是众所周知的,但不容易解决。它真的是create a separate framework for your Core Data Model的最佳方式吗?

1 个答案:

答案 0 :(得分:0)

我有同样的问题,由于某种原因,我无法转换为我的自定义NSManagedObjects进行单元测试,唯一的解决方案是将结果集保存为NSManagedObject Array并访问它是如下字段而不将其转换为ProductModel,对象本身仍然是一个ProductModel,但是它会导致错误。

我将我的模型名称保留为ProductModel而没有MyAppName.ProductModel。

     func testProductModel() {
            let resultFetchRequest = NSFetchRequest(entityName: ProductModel.Name)
            let productModels: [NSManagedObject] = context.executeFetchRequest(resultFetchRequest, error: &error) as!
                    [NSManagedObject]

            if let recipes = productModels[0].valueForKey("recipes") as? NSSet {
                let recipesCount = recipes.count;
                XCTAssertTrue(recipesCount == 0)
            } else {
                XCTFail("FAIL - no recipes nsset")
            }
        }