在 RxSwift 中测试 ViewModel
Testing ViewModel in RxSwift
我想在我的一个 ViewModel 中执行测试,其中包含一个名为 "nearByCity" 的 BehaviorRelay 对象,它绑定到名为 "isNearBy" 的 BehaviorRelay。这就是我的视图模型的样子。
class SearchViewViewModel: NSObject {
//MARK:- Properties
//MARK: Constants
let disposeBag = DisposeBag()
//MARK: Vars
var nearByCity:BehaviorRelay<String?> = BehaviorRelay(value: nil)
var isNearBy = BehaviorRelay(value: true)
//MARK:- Constructor
init() {
super.init()
setupBinders()
}
}
//MARK:- Private methods
private extension SearchViewViewModel{
func setupBinders(){
nearByCity
.asObservable()
.distinctUntilChanged()
.map({[=10=] ?? ""})
.map({[=10=] == ""})
.bind(to: isNearBy)
.disposed(by: disposeBag)
}
}
我想做的测试是实际验证当字符串被接受时,bool值也会根据函数setupBinders()发生变化。
有什么想法吗?
谢谢
这是一种测试方法:
class RxSandboxTests: XCTestCase {
func testBinders() {
let scheduler = TestScheduler(initialClock: 0)
let source = scheduler.createColdObservable([.next(5, "hello"), .completed(10)])
let sink = scheduler.createObserver(Bool.self)
let disposeBag = DisposeBag()
let viewModel = SearchViewViewModel(appLocationManager: StubManager())
source.bind(to: viewModel.nearByCity).disposed(by: disposeBag)
viewModel.isNearBy.bind(to: sink).disposed(by: disposeBag)
scheduler.start()
XCTAssertEqual(sink.events, [.next(0, true), .next(5, false)])
}
}
其他几点:
不要让您的主题属性 var
使用 let
因为您不希望任何人能够用未绑定的版本替换它们。
您必须在此代码中使用 AppLocationManager
的事实并不需要它,这意味着该对象正在做太多事情。在一个视图控制器中拥有多个视图模型并没有什么错,每个视图模型处理视图的不同部分。
最好完全避免在视图模型代码中使用主题(中继),如果需要,最好将它们留在代码的命令式部分。
至少,分解您的 setupBinders 函数,以便各个部分可以独立测试。你的上面可以写成一个简单的、容易测试的、免费的函数:
func isNearBy(city: Observable<String?>) -> Observable<Bool> {
return city
.distinctUntilChanged()
.map {[=11=] ?? ""}
.map {[=11=] == ""}
}
我想在我的一个 ViewModel 中执行测试,其中包含一个名为 "nearByCity" 的 BehaviorRelay 对象,它绑定到名为 "isNearBy" 的 BehaviorRelay。这就是我的视图模型的样子。
class SearchViewViewModel: NSObject {
//MARK:- Properties
//MARK: Constants
let disposeBag = DisposeBag()
//MARK: Vars
var nearByCity:BehaviorRelay<String?> = BehaviorRelay(value: nil)
var isNearBy = BehaviorRelay(value: true)
//MARK:- Constructor
init() {
super.init()
setupBinders()
}
}
//MARK:- Private methods
private extension SearchViewViewModel{
func setupBinders(){
nearByCity
.asObservable()
.distinctUntilChanged()
.map({[=10=] ?? ""})
.map({[=10=] == ""})
.bind(to: isNearBy)
.disposed(by: disposeBag)
}
}
我想做的测试是实际验证当字符串被接受时,bool值也会根据函数setupBinders()发生变化。
有什么想法吗?
谢谢
这是一种测试方法:
class RxSandboxTests: XCTestCase {
func testBinders() {
let scheduler = TestScheduler(initialClock: 0)
let source = scheduler.createColdObservable([.next(5, "hello"), .completed(10)])
let sink = scheduler.createObserver(Bool.self)
let disposeBag = DisposeBag()
let viewModel = SearchViewViewModel(appLocationManager: StubManager())
source.bind(to: viewModel.nearByCity).disposed(by: disposeBag)
viewModel.isNearBy.bind(to: sink).disposed(by: disposeBag)
scheduler.start()
XCTAssertEqual(sink.events, [.next(0, true), .next(5, false)])
}
}
其他几点:
不要让您的主题属性
var
使用let
因为您不希望任何人能够用未绑定的版本替换它们。您必须在此代码中使用
AppLocationManager
的事实并不需要它,这意味着该对象正在做太多事情。在一个视图控制器中拥有多个视图模型并没有什么错,每个视图模型处理视图的不同部分。最好完全避免在视图模型代码中使用主题(中继),如果需要,最好将它们留在代码的命令式部分。
至少,分解您的 setupBinders 函数,以便各个部分可以独立测试。你的上面可以写成一个简单的、容易测试的、免费的函数:
func isNearBy(city: Observable<String?>) -> Observable<Bool> {
return city
.distinctUntilChanged()
.map {[=11=] ?? ""}
.map {[=11=] == ""}
}