在 Swift 测试驱动开发中对 @ObservableObject 进行单元测试
Posted
技术标签:
【中文标题】在 Swift 测试驱动开发中对 @ObservableObject 进行单元测试【英文标题】:Unit testing an @ObservableObject in Swift Test Driven Development 【发布时间】:2020-06-02 14:40:21 【问题描述】:我正在尝试学习如何使用带有 TDD 的 MVVM 架构来解决一些无法在 SwiftUI 中对视图进行单元测试的问题。
我有一个带日期的 Alarm 结构:
import Foundation
struct Alarm
var time: Date
我有一个基本的
class AlarmPickerViewModel: ObservableObject
@Published var alarm: Alarm
init(alarm: Alarm)
self.alarm = alarm
如果AlarmPickerViewModel
不是ObservableObject
的子类并且警报属性不是@Published
,我正在努力研究如何编写一个失败的单元测试。
我查看了this question on the site,但它似乎对我没有帮助。
请指点一下我哪里出错了?
【问题讨论】:
“无法在 SwiftUI 中对视图进行单元测试的一些问题。”那不是真的。在 SwiftUI 中,您可以对视图进行单元测试 - 或至少在视图中测试业务逻辑,因为您可以像使用任何其他实体一样使用依赖注入。 SwiftUI 解决了UIKit
UIViews
和 UIViewController
s 不能依赖注入的问题。唯一不能进行单元测试的部分是 UI 的实际外观。
谢谢,知道这真的很有用。
【参考方案1】:
如果alarm
不是@Published
,您可以创建一个甚至不会编译的测试,只需创建对该属性的订阅,因为您只有在它是@Published
时才能订阅它。
ObservableObject
一致性将objectWillChange
Publisher
添加到您的对象中,因此要对其进行测试,您只需订阅该Publisher
。如果 AlarmPickerViewModel
不是 ObservableObject
,则测试甚至无法编译。
func testAlarmPickerViewModel()
let alarmPickerViewModel = AlarmPickerViewModel(alarm: Alarm(time: .distantFuture))
alarmPickerViewModel.$alarm.sink(receiveValue: print("ViewModel.alarm updated, new value: \($0)") )
alarmPickerViewModel.objectWillChange.sink(receiveValue: print("ViewModel updated: \($0)"))
【讨论】:
以上是关于在 Swift 测试驱动开发中对 @ObservableObject 进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中对这个自定义 UITextField 进行单元测试?