如何对 CloudKit/Core Data 进行单元测试?

Posted

技术标签:

【中文标题】如何对 CloudKit/Core Data 进行单元测试?【英文标题】:How to unit test CloudKit/Core Data? 【发布时间】:2020-04-16 01:04:38 【问题描述】:

我在弄清楚如何为 CloudKit 和 Core Data 制作模拟/存根时遇到了一些麻烦。


我在 CloudKit 服务层方面取得了一些进展,方法是注入一个符合我编写的协议的数据库,该协议基本上覆盖了CKDatabase 函数。

/// A protocol to allow mocking a CKDatabase.
protocol CKDatabaseProtocol 
    func add(_ operation: CKDatabaseOperation)
    func delete(withRecordID recordID: CKRecord.ID, completionHandler: @escaping (CKRecord.ID?, Error?) -> Void)
    func fetch(withRecordID recordID: CKRecord.ID, completionHandler: @escaping (CKRecord?, Error?) -> Void)
    func perform(_ query: CKQuery, inZoneWith zoneID: CKRecordZone.ID?, completionHandler: @escaping ([CKRecord]?, Error?) -> Void)
    func save(_ record: CKRecord, completionHandler: @escaping (CKRecord?, Error?) -> Void)


extension CKDatabase: CKDatabaseProtocol  

有了这个,我可以将真正的CKContainer.default().publicCloudDatabase 注入到我的服务中,或者我可以创建一个符合相同协议的模拟类并将我的MockCKDatabase 注入到我的单元测试服务实例中。这适用于所有功能除了add(operation) 功能。我不确定如何将CKQueryOperation 添加到我的MockCKDatabase 以触发其完成块。


对于核心数据部分,我使用新的NSPersistentCloudKitContainer 来同步用户的私有数据库(同时使用我的 CloudKit 服务对我的公共数据库进行查询)。我发现了一个很好的 blog 创建一个核心数据堆栈,它允许您在设置堆栈时注入存储类型,以便您可以在生产中使用 NSSQLiteStoreType 并在测试中使用 NSInMemoryStoreType

但是,当我尝试使用内存解决方案时,我收到以下错误:

"NSLocalizedFailureReason" : "CloudKit 集成仅支持 SQLite 存储。"

是否有更好的解决方案来测试 CloudKit/Core Data?我真的很想彻底测试我的服务层。

【问题讨论】:

【参考方案1】:

我不确定如何将 CKQueryOperation 添加到我的 MockCKDatabase 以触发其完成块。

您必须自己实现操作的行为。为您使用的每个操作子类编写带有caseswitch 语句。在每种情况下查看操作的属性,执行请求的行为,然后使用适当的结果或错误调用回调。

我现在正在执行此操作,但遇到了障碍。处理CKFetchRecordZoneChangesOperation 涉及返回一个CKServerChangeToken 实例,但由于它没有公共构造函数,因此无法创建这样的对象。而且在获取记录时,无法创建具有指定日期和 changeTags 的 CKRecords。

【讨论】:

以上是关于如何对 CloudKit/Core Data 进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Core Data 对数据进行制表 - 如何有效过滤?

(Swift) 如何对 Core Data 进行模糊搜索?

如何在 GROUP BY 之前对 Core Data 记录进行排序?

如何对 Stack Exchange Data Explorer (SEDE) 结果进行分页?

如何根据相关对象集合的属性对 Core Data 结果进行排序?

Spring Data JPA:如何对 RDS Aurora PostgreSQL 实例之间的读取查询进行负载平衡?