RxSwift:如何在搜索栏中进行单元测试搜索并在表格视图中显示结果

pja*_*e15 5 unit-testing uisearchbar reactive-cocoa swift rx-swift

我已经使用Rxswift一段时间了,并且运行良好。香港专业教育学院设法测试了我所有的代码,但我努力找出如何使用searchbar.rx.bindTo测试搜索。

有很多关于如何使用RxSwift在表视图上搜索和返回结果的教程,但是这些教程都没有向您展示如何对其进行单元测试。 https://www.thedroidsonroids.com/blog/ios/rxswift-by-examples-1-the-basics/

上面的链接显示了我试图用搜索栏并填充TableView想要实现的目标。

香港专业教育学院试图用RxBlocking测试它,但我的测试似乎都死了。systemUnderTest是viewModel结果是从服务返回的Observable <[T]>。

let results = systemUnderTest.results.toBlocking()
    let noneObservableList = try! results.single()

    //Then
    XCTAssert(noneObservableList?.count == expectedCount)
Run Code Online (Sandbox Code Playgroud)

它挂在尝试!result.single()永远不会命中断言。任何人都知道如何测试。

提前致谢。

这是systemUnderTest:

public class SearchViewModel: SearchViewModelContract {

public var query: Variable<String?> = Variable(String.EmptyString())
public var results: Observable<[ThirdPartySite]>
let minimumCharacterCount = 4
let dueTime = 0.3
let disposeBag = DisposeBag()

public init() {
    results = Observable.just([Object]())
    results = query.asObservable().throttle(dueTime, scheduler: MainScheduler.instance).flatMapLatest{
        queryString  -> Observable<Object> in

        if let queryString = queryString {
            if queryString.characters.count >= self.minimumCharacterCount {
                return self.Something(siteName: queryString)
            }
            return Observable.just(Object(in: Object()))
        }
        return Observable.just(Object(in: Object()))
        }.map { results in
            return results.items
        }.catchErrorJustReturn([Object]()).shareReplay(1)
    }
}
Run Code Online (Sandbox Code Playgroud)

Dan*_* T. 2

我有一些建议:

  • query并且results都应该是 let,而不是 vars。你永远不应该重置 Observable 类型。这是功能性含义的一部分。
  • 您似乎使用的是旧版本的 RxSwift;我建议你升级。- 编辑:哦!当然是旧版本的RxSwift,这是一个老问题!
  • 嵌入有副作用(网络调用)的单元测试代码可能是一个巨大的 PITA。将副作用提升到一个更高的水平,这样您就可以在没有它的情况下对其进行单元测试。
  • 该运营商比数据发射debounce更适合。throttle后者更适合触发器。

至于您关于如何对搜索进行单元测试的主要问题,我发现RxTest. 以下是生成 searchTerm Observable 的代码以及证明其有效的测试:

extension ObservableType where Element == String? {

    func searchTerm(minCharacterCount: Int = 4, dueTime: RxTimeInterval = .milliseconds(300), scheduler: SchedulerType = MainScheduler.instance) -> Observable<String> {
        return self
            .compactMap { $0 }
            .filter { minCharacterCount <= $0.count }
            .debounce(dueTime, scheduler: scheduler)
    }
}

class Tests: XCTestCase {

    var scheduler: TestScheduler!
    var result: TestableObserver<String>!
    var disposeBag: DisposeBag!

    override func setUp() {
        super.setUp()
        scheduler = TestScheduler(initialClock: 0, resolution: 0.001)
        result = scheduler.createObserver(String.self)
        disposeBag = DisposeBag()
    }

    func testExample() {
        let input = scheduler.createColdObservable([
            .next(1000, Optional.some("")),
            .next(2000, Optional.some("xyz")),
            .next(3000, Optional.some("wxyz")),
            .next(4000, Optional.some("vwxyz")),
            .next(4300, Optional.some("uvwxyz"))
            ])

        input
            .searchTerm(scheduler: scheduler)
            .subscribe(result)
            .disposed(by: disposeBag)

        scheduler.start()

        XCTAssertEqual(result.events, [.next(3300, "wxyz"), .next(4600, "uvwxyz")])
    }
}
Run Code Online (Sandbox Code Playgroud)

这些flatMapLatest应该放在你的副作用代码中,那些你不进行单元测试的东西。