我有一个简单的ViewModel
,其中包含一个属性:
class ViewModel {
var name = Variable<String>("")
}
我将UITextField
绑定到ViewController
:
class ViewController : UIViewController {
var viewModel : ViewModel!
@IBOutlet weak var nameField : UITextField!
private let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// Binding
nameField.rx.text
.orEmpty
.bind(to: viewModel.name)
.disposed(by: disposeBag)
}
}
现在,我想进行单元测试。
我可以使用nameField.text
事件 - .onNext
通过Rx填充nameField.rx.text.onNext("My Name Here")
媒体资源。
但viewModel.name
并未被填补。为什么?如何在我的XCTestCase中使这个Rx行为起作用?
请参阅下面我上次测试的结果:
答案 0 :(得分:2)
我相信您遇到的问题是绑定未在主线程上明确安排。我建议在这种情况下使用Driver
:
class ViewModel {
var name = Variable<String>("")
}
class ViewController: UIViewController {
let textField = UITextField()
let disposeBag = DisposeBag()
let vm = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
textField.rx.text
.orEmpty
.asDriver()
.drive(vm.name)
.disposed(by: disposeBag)
}
// ..
使用Driver
,绑定将始终发生在主线程上,并且不会出错。
另外,在你的测试中,我会在绑定上调用skip
:
sut.nameTextField.rx.text.skip(1).onNext(name)
因为Driver
会在订阅时重播第一个元素。
最后,我建议使用RxTest和TestScheduler
代替GCD。
如果有帮助,请告诉我。
答案 1 :(得分:0)
rx.text依赖于以下UIControlEvent:.allEditingEvents
和.valueChanged
。因此,显式发送onNext事件将不会为这些事件发送动作。您应该手动发送操作。
sut.nameField.rx.text.onNext(name)
sut.nameField.sendActions(for: .valueChanged)