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

如何对使用单例模式的模型控制器及UIViewController进行单元测试

前置说明

你提供的代码存在两处可提前修复的编译/逻辑问题,修复后更便于后续测试:

  1. Entry为值类型且title、body声明为let常量,现有updateEntry方法修改的是传入的Entry副本,既会触发编译报错,也无法同步修改到entries数组中
  2. Entry未实现Equatable协议,destroyEntry方法中调用index(of:)会触发编译报错

问题1:如何测试单例CRUD函数,以及单元测试覆盖范围

  • 单例测试的核心痛点是全局状态会在多个测试用例之间互相污染,解决方案如下:
    1. 先定义抽象协议,解耦业务代码对单例的直接依赖:
protocol EntryControllerProtocol {
    var entries: [Entry] { get set }
    func newEntry(title: String, body: String)
    func updateEntry(title: String, body: String, entry: Entry)
    func destroyEntry(entry: Entry)
}
// 让原有EntryController实现该协议
extension EntryController: EntryControllerProtocol {}
  1. 测试时不要使用EntryController.shared,每次测试都初始化独立的EntryController实例,从根源避免状态互相影响
  2. CRUD基础测试用例:
    - 新增:调用newEntry前entries为空,调用后数组长度为1,元素的title、body与入参一致
    - 更新:先插入测试Entry,调用update后验证数组中对应位置的Entry属性符合预期(需先修复原update方法的bug)
    - 删除:先插入测试Entry,调用destroyEntry后entries为空;删除不存在的Entry时无崩溃、无异常
  • 单元测试覆盖范围不局限于单个函数,还要覆盖对应单元的所有行为边界:比如空数据处理、非法入参处理、重复数据插入/删除的表现等,只要是EntryController对外承诺的行为都属于测试范围。

问题2:CRUD改为静态函数后的测试方法

静态函数本质是操作全局静态存储的entries数组,测试核心是每次测试前重置全局状态:

  1. 保持抽象协议的设计,静态方法同样可以在协议中声明
  2. 在测试用例的setUp方法中,每次执行测试前都将静态的entries数组重置为空数组,避免上一个测试的残留数据影响下一个测试的结果
  3. 测试用例逻辑和普通实例方法的测试完全一致,仅调用方从实例改为类本身即可
    注:静态方法的全局状态特性天生不便于测试,非必要场景更推荐使用依赖注入的实例方案

问题3:UIViewController的单元测试方法

核心思路是对控制器的外部依赖做注入,避免依赖全局单例,同时单独测试控制器的业务逻辑:

  1. 先改造EntryViewController,把对EntryController.shared的硬编码改为可注入的依赖:
class EntryViewController: TableViewController {
    // 依赖注入,默认值为生产环境的单例
    var entryController: EntryControllerProtocol = EntryController.shared
    // 原有其他代码保持不变,把所有用到EntryController.shared的地方替换为entryController
}
  1. 测试数据源方法:
  • 测试numberOfRowsInSection:给注入的entryController传入指定数量的测试Entry,验证方法返回值和Entry数量一致
  • 测试cellForRowAt:提前给测试用的tableView注册对应identifier的UITableViewCell,调用方法后验证cell的textLabel、detailTextLabel内容与对应位置的Entry属性一致
  • 空数据测试:entryController的entries为空时,验证数据源方法返回0,不会出现数组越界崩溃
  1. 如果需要测试交互逻辑(比如左滑删除、点击跳转),可以通过调用对应代理方法,验证依赖的entryController是否执行了对应操作即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 11:36:02