You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS开发新手:如何编写测试验证视图控制器带动画Dismiss

嘿,我来帮你搞定这个AboutViewController的单元测试问题!😎

要测试homeButtonTouched(_:)方法是否正确调用了带动画的dismiss,我们可以通过创建一个Mock视图控制器来跟踪dismiss方法的调用情况——毕竟直接测试控制器是否消失在单元测试里不太直观,而验证方法调用和参数才是单元测试的核心。

完整的测试实现步骤:

  1. 首先在你的测试类里定义一个MockViewController,用来记录dismiss的调用状态和参数:
class MockViewController: UIViewController {
    // 记录dismiss是否被调用
    var didTriggerDismiss = false
    // 记录dismiss时传入的animated参数值
    var dismissAnimatedFlag: Bool?
    
    override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
        // 更新记录状态
        didTriggerDismiss = true
        dismissAnimatedFlag = flag
        // 调用父类方法保证正常流程
        super.dismiss(animated: flag, completion: completion)
    }
}
  1. 然后填充testHomeButtonTouched()方法的内容:
func testHomeButtonTouched() {
    // 1. 创建Mock控制器作为AboutVC的presenting控制器
    let mockPresenter = MockViewController()
    // 2. 用Mock控制器present我们的AboutVC(这里不需要动画,不影响测试)
    mockPresenter.present(aboutViewController, animated: false)
    
    // 3. 直接触发按钮点击方法(模拟用户点击)
    aboutViewController.homeButtonTouched(UIButton())
    
    // 4. 验证核心逻辑:dismiss被调用,且animated参数为true
    XCTAssertTrue(mockPresenter.didTriggerDismiss, "点击Home按钮应该触发dismiss方法")
    XCTAssertEqual(mockPresenter.dismissAnimatedFlag, true, "dismiss应该带动画执行")
}

为什么这么做?

  • 我们的目标是测试homeButtonTouched(_:)的业务逻辑:点击按钮 → 调用dismiss(animated: true),而不是测试UIKit的dismiss功能本身(那是苹果的工作😉)。
  • 通过Mock控制器,我们可以精准跟踪方法调用的细节,确保参数符合预期,这比直接观察UI消失要可靠得多。

如果想要更严谨地等待动画完成(虽然单元测试里通常不需要),可以加上XCTestExpectation来异步等待:

func testHomeButtonTouchedWithAnimationWait() {
    let mockPresenter = MockViewController()
    mockPresenter.present(aboutViewController, animated: false)
    
    let dismissExpectation = self.expectation(description: "等待dismiss动画完成")
    
    // 延迟等待动画队列完成
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
        dismissExpectation.fulfill()
    }
    
    aboutViewController.homeButtonTouched(UIButton())
    
    waitForExpectations(timeout: 1, handler: nil)
    
    XCTAssertTrue(mockPresenter.didTriggerDismiss)
    XCTAssertEqual(mockPresenter.dismissAnimatedFlag, true)
}

不过对于单元测试来说,第一种方法已经完全足够覆盖需求啦!

内容的提问来源于stack exchange,提问作者Erika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:37:18