我有一个Swift应用程序,它使用NSFetchedResultsController从持久存储中获取List对象:
let fetchedResultsController: NSFetchedResultsController = ...
var error : NSError?
fetchedResultsController.performFetch(&error)
if let error = error {
    NSLog("Error: \(error)")
}
let lists: [List] = fetchedResultsController.fetchedobjects! as [List]
NSLog("lists count = \(lists.count)")
for list: List in lists {
    NSLog("List: \(list.description)")
}

它的工作方式与预期的一样,我将List对象描述打印到控制台.
我想为我的应用程序编写一些单元测试,所以我创建了扩展XCTestCase的类.代码编译没有问题,测试运行,但不幸的是我无法在该上下文中获取List对象.

我在控制台中获得的所有内容都是List对象的数量和致命错误:

lists count = 59
Fatal error: NSArray element Failed to match the Swift Array Element type

线路上升:

for list: List in lists {

我很确定我已经正确配置了目标,因为我可以创建List对象并将其插入到托管对象上下文中,而不会出现我的应用程序源代码以及单元测试源代码的问题.我遇到的唯一问题是从测试单元获取.我想知道为什么在模拟器中运行应用程序时提取工作正常,并且在单元测试期间执行时失败.

任何可能出错的想法都将受到赞赏.

更新:

更具体地说,我的实现如何,这里是我正在玩的完整代码示例:

var error: NSError? = nil

let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,inDomains: .UserDomainMask)
let applicationDocumentsDirectory = urls[urls.count-1] as NSURL

let modelURL = NSBundle.mainBundle().URLForResource("CheckLists",withExtension: "momd")!
let managedobjectModel = NSManagedobjectModel(contentsOfURL: modelURL)

var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedobjectModel: managedobjectModel)
let url = applicationDocumentsDirectory.URLByAppendingPathComponent("CheckLists.sqlite")
if coordinator!.addPersistentStoreWithType(NSsqliteStoreType,configuration: nil,URL: url,options: nil,error: &error) == nil {
    NSLog("Error1: \(error)")
    abort()
}

var managedobjectContext = NSManagedobjectContext()
managedobjectContext.persistentStoreCoordinator = coordinator

let fetchRequest = NSFetchRequest()
fetchRequest.entity = NSEntityDescription.entityForName("List",inManagedobjectContext: managedobjectContext)
fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "name",ascending: true) ]

let fetchedResultsController = NSFetchedResultsController(
    fetchRequest: fetchRequest,managedobjectContext: managedobjectContext,sectionNameKeyPath: nil,cacheName: "ListFetchedResultsControllerCache"
)

fetchedResultsController.performFetch(&error)
if let error = error {
    NSLog("Error2: \(error)")
    abort()
}

let fetchedobjects: [AnyObject]? = fetchedResultsController.fetchedobjects
if let fetchedobjects = fetchedobjects {
    NSLog("Fetched objects count: \(fetchedobjects.count)")
    for fetchedobject in fetchedobjects {
        NSLog("Fetched object: \(fetchedobject.description)")
    }
}
else {
    NSLog("Fetched objects array is nil")
}

let fetchedLists: [List]? = fetchedResultsController.fetchedobjects as? [List]
if let fetchedLists = fetchedLists {
    NSLog("Fetched lists count: \(fetchedLists.count)")
    for fetchedList in fetchedLists {
        NSLog("Fetched list: \(fetchedList.description)")
    }
}
else {
    NSLog("Fetched lists array is nil")
}

当我从应用程序的源代码执行它,在模拟器中运行应用程序时,控制台输出如下所示:

Fetched objects count: 3
Fetched object: <CheckLists.List: 0x7a6866f0> (entity: List; id: 0x7a686020 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
    name = "List 1";
})
Fetched object: <CheckLists.List: 0x7a686930> (entity: List; id: 0x7a686030 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
    name = "List 2";
})
Fetched object: <CheckLists.List: 0x7a686970> (entity: List; id: 0x7a686040 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
    name = "List 3";
})
Fetched lists count: 3
Fetched list: <CheckLists.List: 0x7a6866f0> (entity: List; id: 0x7a686020 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
    name = "List 1";
})
Fetched list: <CheckLists.List: 0x7a686930> (entity: List; id: 0x7a686030 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
    name = "List 2";
})
Fetched list: <CheckLists.List: 0x7a686970> (entity: List; id: 0x7a686040 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
    name = "List 3";
})

但是,当我从单元测试中执行此代码时,我得到此输出:

Fetched objects count: 3
Fetched object: <CheckLists.List: 0x7a07df50> (entity: List; id: 0x7a07d7e0 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p2> ; data: {
    name = "List 1";
})
Fetched object: <CheckLists.List: 0x7a07e190> (entity: List; id: 0x7a07d7f0 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p1> ; data: {
    name = "List 2";
})
Fetched object: <CheckLists.List: 0x7a07e1d0> (entity: List; id: 0x7a07d800 <x-coredata://7A87B5BE-C2FA-4150-B9E3-879FDE07F0B9/List/p3> ; data: {
    name = "List 3";
})
Fetched lists array is nil

我希望它更容易理解问题所在.不知何故,这句话:

let fetchedLists: [List]? = fetchedResultsController.fetchedobjects as? [List]

当app在模拟器中运行时,会生成一个List对象数组,但是当从单元测试执行时,它无法生成nil.

该问题与目标配置相关联.我通过一些解决方法解决了这个问题.

以前,为了使List实体类可以在我的单元测试目标中访问,我已将它添加到此目标.因此,List类有两个目标.实际上,Swift已知有两个List类,每个目标对应一个:MyAppTarget.List和MyUnitTestTarget.List. Retched结果控制器返回MyAppTarget.List对象的数组,但在单元测试目标中,List被假定为MyUnitTestTarget.List类.这就是这行代码:

let fetchedLists: [List]? = fetchedResultsController.fetchedobjects as? [List]

从单元测试目标执行时生成nil,而不是从主目标执行时生成的正确数组.为了解决这个问题,我将其更改为:

let fetchedLists: [MyAppTarget.List]? = fetchedResultsController.fetchedobjects as? [MyAppTarget.List]

并使List类公开.在那次改变之后,它会像预期的那样工作

但是,对我来说,MyAppTarget.List无法转换为MyUnitTestTarget.List有点让人困惑.而且,这意味着我需要公开每个实体NSManagedobject子类,以便在单元测试中使用它.到目前为止,我找不到更好的解决方案.

也许有更好的方法来解决这个问题.我没有看到告诉NSFetchedResultsController它应该返回主目标中的MyAppTarget.List和单元测试目标中的MyUnitTestTarget.List的选项.它将始终使用.xcdatamodeld文件中给定实体的配置.此外,即使有一种方法将MyAppTarget.List转换为单元测试中的MyUnitTestTarget.List,它仍然需要List类是公共的.

更新:

我找到了一种在运行时更改NSFetchedResultsController返回的实体类的方法.这是一个更清晰简单的解决方案:https://stackoverflow.com/a/25858758/514181

它允许在单元测试中无缝地使用CoreData实体,而无需强制转换或使实体类公开.

unit-testing – 如何在Swift中对NSFetchedResultsController进行单元测试的更多相关文章

  1. 如何通过代码设置iOS的系统时区?

    我想通过代码在iOS中设置系统时区,日期时间.任何想法或私人api帮助我?示例:将时区设置为GMT8,将日期时间设置为2013年8月10日晚上8:30.怎么做?

  2. ios – 多个NSPersistentStoreCoordinator实例可以连接到同一个底层SQLite持久性存储吗?

    我读过的关于在多个线程上使用CoreData的所有内容都讨论了使用共享单个NSPersistentStoreCoordinator的多个NSManagedobjectContext实例.这是理解的,我已经使它在一个应用程序中工作,该应用程序在主线程上使用CoreData来支持UI,并且具有可能需要一段时间才能运行的后台获取操作.问题是NSPersistentStoreCoordinator会对基础

  3. ios – CoreData有序关系 – 使用NSFetchRequest批量取消

    或者,是否存在批量不支持的API,它不是私有的?解决方法目前我有一个解决方案,但不是一个干净的解决方案:我希望按照有序关系中的20个小组进行批量修改.所以,每次我索引一个索引,它的索引除以20,我为接下来的20使用新的NSFetchRequest,并通过调用公共字段名称来解除它们.

  4. ios – 使用SQLite和CoreData进行批量插入

    我有一个使用sqlite作为持久性存储的CoreData模型.在对每条记录进行一些处理之后,我需要插入大量的行.有没有办法将这些命令发送到sqlite我需要加快处理时间,因为它需要几个小时才能完成.任何提示将不胜感激.谢谢解决方法将商店添加到商店协调员时,可以指定编译指示:(改编自PersistentStoreFeatures)我强烈建议您阅读“有效导入数据”.相关文档:NSSQLitePragm

  5. 核心数据 – iOS:由于Xcode 9中的Fetched Indexes,无法编译CoreData模型

    根据发行说明,Xcode9增加了对获取索引的支持:“ThedatamodeleditorpresentsaunifiedinterfaceforCoreData’snewfetchindexesfeatureaswellasitsexistingpropertyindexandentitycompoundindexfeatures.Olderdatamodelsaretranslatedintof

  6. 如何在Cocoa中使用Bindings CoreData实现iTunes风格的Source-List?

    让我们说,为了说明,我在Cocoa中编写了一个iTunes克隆应用程序,该应用程序由CoreData支持.为简化起见,假设有两个“部分”,“图书馆”,包括音乐,电影,广播等.第二部分称为“播放列表”,其中包含用户生成的播放列表.所以SourceList本身通常会用NSOutlineView实现,这通常很简单.源列表的“库”部分实际上并不包含用户生成的任何内容,只包含应用程序的“功能”(实质上),其中“播放列表”部分仅包含用户创建的自定义列表.如何用Bindings和CoreData做到这一点?

  7. ios – 未为测试目标生成核心数据类

    我使用CoreData的自动生成的类.除测试目标外,我的项目还有3个目标.对于每个目标,正确生成CoreData类,我通过检查DerivedData文件夹进行验证.但是,尽管在核心数据模型文件中打勾,但不会为测试目标生成类.当我尝试引用测试目标中的一个CoreData类时,这会导致“未声明的标识符”和“使用未声明的类型”错误.我该如何解决这个问题?

  8. ios – 如何为NSNotification编写单元测试

    我在swift工作,我想刷新一个页面,所以我使用通知发送它,我在一个ViewController中发布通知并在另一个中添加观察者,它工作正常.我想要做的是在swift中添加单元测试.我查了很多网站但是没能做到.我是新手,不知道从哪里开始.基本上工作是,当我点击按钮通知被发布时,并且当加载下一个视图控制器时,添加通知观察者.我该怎么做单元测试提前致谢编辑:码并添加观察者解决方法一般的解决方案是:使用

  9. 如何在iOS中为预期的assert / assertionFailure编写单元测试?

    这里的问题是,当someString参数为空字符串时,您可以保证函数不会失败–在您的实际应用程序中.这是因为断言不在发布版本中运行.结果是你可以在开发过程中使用assert作为调试的一种形式,但如果这种情况在现实生活中发生,你应该按顺序处理它,而不是崩溃.因此测试断言“发生”是否真的不是一种有效的单元测试技术,这就是为什么你以这种方式使用它的麻烦.

  10. ios – 尽管匹配x-coredata id,“CoreData不支持持久的跨店关系”

    有关AbstractSource,我在源代码中没有触摸/控制?我是通过调用来创建Quote和BookinitWithEntity:insertIntoManagedobjectContexteach.)>我注意到错误描述还包括几个“相对的”x-coredataid(形式为“x-coredata:///……”如果是这样,我怎么能影响“绝对”和“绝对”之间的任何选择“相对”x-coredataid?

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部