启用和禁用 iCloud 时的 XCTest

Posted

技术标签:

【中文标题】启用和禁用 iCloud 时的 XCTest【英文标题】:XCTest for when iCloud is enabled and disabled 【发布时间】:2019-01-17 16:48:39 【问题描述】:

我有一个 viewMode 来确定是启用还是禁用 iCloud,结果是提示用户登录 iCloud。

有没有办法从 XCTest 以编程方式登录/注销到 iCloud 以可靠地测试所有路径?

这是我的测试

func testShowLoginButtonForiCloud() 
  let viewModel = OnboardingViewModel()
  let expectation = XCTestExpectation(description: "Wait for CKContainer auth check")
  var iCloudEnabled: Bool?

  viewModel.shouldShowiCloudLogin  result, error in
    iCloudEnabled = result
    expectation.fulfill()
  
  wait(for: [expectation], timeout: 5.0)

  XCTAssertNotNil(iCloudEnabled)
  XCTAssertFalse(iCloudEnabled!)

这是我的视图模型

typealias Completion = (Bool, Error?) -> Void

final class OnboardingViewModel 
  func shouldShowiCloudLogin(completion: @escaping Completion) 
  CKContainer.default().accountStatus  (status, error) in
    switch status 
      case .available :
        completion(true, nil)
       default :
        completion(false, error)
      
    
  

【问题讨论】:

这是一个细节,但我想玩代码:你能添加Completion的定义吗?你是不是想拥有它@escaping 成功是因为我认为我需要保留局部变量。 我更新了评论以包含 typealias。这是一个接受布尔值和可选错误的函数。 【参考方案1】:

我们可以通过编程方式登录 CloudKit 进行单元测试吗?这是不可取的,因为即使我们可以,测试也会很慢而且很脆弱。相反,将 CloudKit 视为架构边界。单元测试可以直接达到这个边界。我们可以假装东西从边界回来。这样,我们就可以测试所有的路径了。

要将此边界编程到您的代码中,请使用协议。这个协议将是一个只包含你想要的 CKContainer 方法的切片。 (这就是实际的接口隔离原则。)由于 CKContainer 已经实现了这个方法,我们可以将它附加为一个空扩展。

protocol CKContainerProtocol 
    func accountStatus(completionHandler: @escaping (CKAccountStatus, Error?) -> Void)


extension CKContainer: CKContainerProtocol 

然后给你的视图模型添加一个属性:

var cloudKitContainer: CKContainerProtocol = CKContainer.default()

默认值意味着您的代码将继续使用真正的 CKContainer,除非另有说明。将您的代码更改为调用cloudKitContainer 而不是CKContainer.default()

然后在测试代码中,可以提供CKContainerProtocol的不同实现。这将使您可以进行存根和模拟。您可以确认accountStatus() 只被调用了一次。您可以使用不同的 CKAccountStatus 值来执行它的闭包,以确认您的 Completion 闭包是如何被调用的。

【讨论】:

以上是关于启用和禁用 iCloud 时的 XCTest的主要内容,如果未能解决你的问题,请参考以下文章

iOS 7 iCloud 和(启用/禁用)Core Data - 永无止境的故事

未启用 iCloud 时如何存储核心数据日志?

应用程序关闭时的 iOS 定位服务启用/禁用事件

iCloud Core 数据同步设置

从代码启用/禁用 VR

如何在 iOS 7 App 中禁用 iCloud