2

我想在我的一个 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({$0 ?? ""})
            .map({$0 == ""})
            .bind(to: isNearBy)
            .disposed(by: disposeBag)

    }

}

我要执行的测试是实际验证当字符串被接受时,布尔值也会根据函数 setupBinders() 发生变化。

任何想法?

谢谢

4

1 回答 1

3

这是一种测试方法:

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 == ""}
}
于 2019-06-11T12:29:08.550 回答