Я хотел бы выполнить тест в одной из моих моделей ViewModel, которая содержит объект BehaviorRelay с именем «nearByCity», который привязан к BehaviorRelay с именем «isNearBy». Вот так выглядит моя модель представления.
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({$0 ?? ""})
.map({$0 == ""})
.bind(to: isNearBy)
.disposed(by: disposeBag)
}
}
Тест, который я хочу выполнить, состоит в том, чтобы на самом деле убедиться, что когда строка принимается, логическое значение также изменяется в соответствии с функцией 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 {$0 ?? ""}
.map {$0 == ""}
}
Большое спасибо за информацию и за подсказку! Да, я собираюсь отредактировать вопрос, потому что я извлек код из большего класса.
RxTest и RxBlocking используются для тестирования. Прочтите несколько статей о них