我在当前工作的项目中使用ModelView-ViewModel
,并使用RxSwift
、RxBlocking
&RxTests
。目前,我正在尝试测试ViewModel,但遇到了很多问题。
假设我的ExampleViewController
有一个ExampleViewModel
。我的ExampleViewModel
期望Observable
流,它是来自UITextField
的两个流的组合(combineLatest
),一个是如果textField是焦点的,另一个是文本流;所以类似CCD_ 11。根据是否聚焦和字符串的上下文,我的ExampleViewModel
将向其内部公开的属性发出一个事件,该属性是Observable
——UITextField
的backgroundColor的状态;Observable<UIColor>
。
ExampleViewModel.swift
:
class ExampleViewModel {
private let disposeBag = DisposeBag()
private let _textFieldColor: PublishSubject<UIColor>
var textFieldColor: Observable<UIColor> { get { return self._textFieldColor.asObservable() } }
init(textFieldObservable: Observable<(Bool, String)>) {
textFieldObservable.subscribeNext { (focus, text) in
self.validateTextField(focus, text: text)
}.addDisposableTo(self.disposeBag)
}
func validateTextField(focus: Bool, text: String) {
if !focus && !text.isEmpty {
self._textFieldColor.onNext(UIColor.whiteColor())
} else {
self._textFieldColor.onNext(UIColor.redColor())
}
}
}
(对不起,我不知道如何正确格式化)
基本上,我想测试ExampleViewModel
类,并通过控制焦点和文本输入来测试它是否发出正确的UIColor
。
感谢
感谢同事的建议,我找到了一种更好的方法来构建ExampleViewModel
以进行可测试性。通过使用ExampleViewModel
分离验证方法,并使用其中使用验证器的map
运算符设置textFieldColor
Observable
,验证在外部进行,而不使用Rx
,简化了逻辑的测试。
ExampleViewModel
class ExampleViewModel {
var textFieldColor: Observable<UIColor>
init(
textFieldText: Observable<String>,
textFieldFocus: Observable<Bool>,
validator: TextFieldValidator
) {
self. textFieldColor = Observable.combineLatest(textFieldText, textFieldFocus) { ($0, $1) }. map { validator.validate($1, text: $0) }
}
}
class TextFieldValidator {
func validate(focus: Bool, text: String) -> UIColor {
if !focus && !text.isEmpty {
return UIColor.whiteColor()
} else {
return UIColor.redColor()
}
}
}