如何对 CloudKit/Core Data 进行单元测试? [英] How to unit test CloudKit/Core Data?
问题描述
我在弄清楚如何为 CloudKit 和 Core Data 制作模拟/存根时遇到了一些麻烦.
I'm having some trouble figuring out how to make mocks/stubs for CloudKit and Core Data.
通过注入符合我编写的协议的数据库,我在 CloudKit 服务层上取得了一些进展,该协议基本上覆盖了 CKDatabase
函数.
I have made some progress with my CloudKit service layer by injecting a database which conforms to a protocol I've written that essentially overrides CKDatabase
functions.
/// 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
code> 进入我的单元测试服务实例.这适用于所有功能除了add(operation)
函数.我不确定如何将 CKQueryOperation
添加到我的 MockCKDatabase
以触发其完成块.
With this, I can inject the real CKContainer.default().publicCloudDatabase
into my service or I can create a mock class that conforms to the same protocol and inject my MockCKDatabase
into my unit tests service instance. This works for all the functionality except the add(operation)
function. I'm not sure how to get a CKQueryOperation
added to my MockCKDatabase
to have its completion blocks triggered.
对于核心数据部分,我使用新的 NSPersistentCloudKitContainer
来同步用户的私有数据库(同时使用我的 CloudKit 服务查询我的公共数据库).我找到了一个关于创建核心的优秀博客允许您在设置堆栈时注入存储类型的数据堆栈,以便您可以在生产中使用 NSSQLiteStoreType
和在测试中使用 NSInMemoryStoreType
.
For the Core Data portion, I am using the new NSPersistentCloudKitContainer
to sync the user's private database (while using my CloudKit service to make queries to my public database). I found an excellent blog about creating a Core Data stack that allows you to inject the store type when setting up the stack so that you can use NSSQLiteStoreType
in production and NSInMemoryStoreType
in testing.
但是,当我尝试使用内存解决方案时,出现以下错误:
However, when I try to use the in-memory solution I get the following error:
"NSLocalizedFailureReason" : "CloudKit 集成仅支持 SQLite 存储."
"NSLocalizedFailureReason" : "CloudKit integration is only supported for SQLite stores."
是否有更好的解决方案来测试 CloudKit/Core Data?我真的很想彻底测试我的服务层.
Is there some better solution to test CloudKit/Core Data? I would really like to have my service layers thoroughly tested.
推荐答案
我不确定如何将 CKQueryOperation 添加到我的 MockCKDatabase 以触发其完成块.
I'm not sure how to get a CKQueryOperation added to my MockCKDatabase to have its completion blocks triggered.
您必须自己实现操作的行为.为您使用的每个操作子类编写带有 case
的 switch
语句.在每种情况下查看操作的属性,执行请求的行为,然后使用适当的结果或错误调用回调.
You have to implement the operation's behavior yourself. Write a switch
statement with a case
for each operation subclass that you use. In each case look at the properties of the operation, do the requested behavior, and then call the callback with the appropriate result or error.
我现在正在做这件事,但遇到了障碍.处理 CKFetchRecordZoneChangesOperation
涉及返回一个 CKServerChangeToken
实例,但无法创建这样的对象,因为它没有公共构造函数.并且在获取记录时,无法创建具有指定日期和 changeTags 的 CKRecords.
I'm halfway through doing this right now, but running into roadblocks. Handling CKFetchRecordZoneChangesOperation
involves returning a CKServerChangeToken
instance, but there's no way to create such an object since it has no public constructor. And when fetching records, there's no way to create CKRecords with specified dates and changeTags.
这篇关于如何对 CloudKit/Core Data 进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!