本文主要介绍如何对 ReactorKit 客户代码单元测试.

使用 ReactorKit 时候的单元测试可以按如下进行.

1 测什么?

  • View(在 iOS 中通常是 ViewController 作为广义的 View 存在)
    • Action: 是否合适的行为被发送给了 reactor
    • State: 当状态改变后, 视图的属性是否被正确更新
  • Reactor
    • State: 当动作接收到后(输入), 是否正确更新状态(输出).

2 怎么测?

针对 View, 可以使用 stub Reactor, 通过直接手动改变 Reactor 的状态, 来检验视图的属性是否正常改变:

swift
/// 演示外界事件触发动作发送(动作发送的结果是 Reactor 接收到 action, 所以要通过 stub 里面的数据来验证)
func testAction_refresh() {
  let reactor = MyReactor()
  reactor.stub.isEnabled = true

  let view = MyView()
  view.reactor = reactor

  view.refreshControl.sendActions(for: .valueChanged) // 在代码里面模拟用户行为

  XCTAssertEqual(reactor.stub.actions.last, .refresh) // 检验动作是否正确发送
}

/// 演示 Reactor 的状态改变(Reactor 的输出)改变视图的属性, 通过验证属性是否改变来达到目的.
func testState_isLoading() {
  let reactor = MyReactor()
  reactor.stub.isEnabled = true

  let view = MyView()
  view.reactor = reactor

  // 设置 stub reactor 的属性值改变
  reactor.stub.state.value = MyReactor.State(isLoading: true)

  // 验证视图属性是否被正确改变
  XCTAssertEqual(view.activityIndicator.isAnimating, true)
}

针对 Reactor, 完全可以单独测试(它自己的依赖也可以通过 Mock 或 Stub 来模拟).

swift
func testIsBookmarked() {
  let reactor = MyReactor()
  
  // 发送动作并验证
  reactor.action.onNext(.toggleBookmarked)
  XCTAssertEqual(reactor.currentState.isBookmarked, true)
  
  reactor.action.onNext(.toggleBookmarked)
  XCTAssertEqual(reactor.currentState.isBookmarked, false)
}

针对更复杂的情况, 就需要使用 Rx 提供的测试工具来完成了, 比如 RxTest 等, 详见这里.