Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/117.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios RxSwift,使用RxBlock的测试不会结束_Ios_Swift_Rx Swift_Rx Blocking - Fatal编程技术网

Ios RxSwift,使用RxBlock的测试不会结束

Ios RxSwift,使用RxBlock的测试不会结束,ios,swift,rx-swift,rx-blocking,Ios,Swift,Rx Swift,Rx Blocking,我尝试测试一个非常简单的视图模型: struct SearchViewModelImpl: SearchViewModel { let query = PublishSubject<String>() let results: Observable<BookResult<[Book]>> init(searchService: SearchService) { results = query .

我尝试测试一个非常简单的视图模型:

struct SearchViewModelImpl: SearchViewModel {
    let query = PublishSubject<String>()
    let results: Observable<BookResult<[Book]>>

    init(searchService: SearchService) {
        results = query
            .distinctUntilChanged()
            .throttle(0.5, scheduler: MainScheduler.instance)
            .filter({ !$0.isEmpty })
            .flatMapLatest({ searchService.search(query: $0) })
    }
}
我试图测试从服务接收到的错误,因此我通过以下方式将其加倍:

class SearchServiceStub: SearchService {
    let erroring: Bool

    init(erroring: Bool) {
        self.erroring = erroring
    }

    func search(query: String) -> Observable<BookResult<[Book]>> {
        if erroring {
            return .just(BookResult.error(SearchError.downloadError, cached: nil))
        } else {
            return books.map(BookResult.success) // Returns dummy books
        }
    }
}
func test_when_searchBooksErrored_then_nextEventWithError() {
    let sut = SearchViewModelImpl(searchService: SearchServiceStub(erroring: true))
    let observer = scheduler.createObserver(BookResult<[Book]>.self)

    scheduler
        .createHotObservable([
            Recorded.next(200, ("Rx")),
            Recorded.next(800, ("RxSwift"))
        ])
        .bind(to: sut.query)
        .disposed(by: disposeBag)

    sut.results
        .subscribe(observer)
        .disposed(by: disposeBag)

    scheduler.start()

    XCTAssertEqual(observer.events.count, 2)
}
我正在测试一个错误如下的查询:

class SearchServiceStub: SearchService {
    let erroring: Bool

    init(erroring: Bool) {
        self.erroring = erroring
    }

    func search(query: String) -> Observable<BookResult<[Book]>> {
        if erroring {
            return .just(BookResult.error(SearchError.downloadError, cached: nil))
        } else {
            return books.map(BookResult.success) // Returns dummy books
        }
    }
}
func test_when_searchBooksErrored_then_nextEventWithError() {
    let sut = SearchViewModelImpl(searchService: SearchServiceStub(erroring: true))
    let observer = scheduler.createObserver(BookResult<[Book]>.self)

    scheduler
        .createHotObservable([
            Recorded.next(200, ("Rx")),
            Recorded.next(800, ("RxSwift"))
        ])
        .bind(to: sut.query)
        .disposed(by: disposeBag)

    sut.results
        .subscribe(observer)
        .disposed(by: disposeBag)

    scheduler.start()

    XCTAssertEqual(observer.events.count, 2)
}
首先,我只是断言事件的计数是否正确,但我只收到一个而不是两个。我认为这是一个异步问题,所以我将测试改为使用RxBlock:

func test_when_searchBooksErrored_then_nextEventWithError() {
    let sut = SearchViewModelImpl(searchService: SearchServiceStub(erroring: true))
    let observer = scheduler.createObserver(BookResult<[Book]>.self)

    scheduler
        .createHotObservable([
            Recorded.next(200, ("Rx")),
            Recorded.next(800, ("RxSwift"))
        ])
        .bind(to: sut.query)
        .disposed(by: disposeBag)

    sut.results.debug()
        .subscribe(observer)
        .disposed(by: disposeBag)

    let events = try! sut.results.take(2).toBlocking().toArray()

    scheduler.start()

    XCTAssertEqual(events.count, 2)
}
但这永远不会结束

我不知道我的存根是否有问题,或者viewmodel是否有问题,但生产应用程序工作正常,在查询启动时发出事件


RxTest和RXBLOCK的文档非常简短,有一个字符串或整数的经典示例,但与这种流无关。。。这非常令人沮丧。

您使用MainScheduler.instance scheduler限制查询。试着移除它,看看会发生什么。这可能就是为什么你只能得到一个。在测试时,您需要将测试调度程序注入该节流阀

有几种不同的方法可以将正确的调度程序引入到您的模型中。根据您当前的代码,依赖项注入可以正常工作

struct SearchViewModelImpl: SearchViewModel {
    let query = PublishSubject<String>()
    let results: Observable<BookResult<[Book]>>

    init(searchService: SearchService, scheduler: SchedulerType = MainScheduler.instance) {
        results = query
            .distinctUntilChanged()
            .throttle(0.5, scheduler: scheduler)
            .filter({ !$0.isEmpty })
            .flatMapLatest({ searchService.search(query: $0) })
    }
}
此外,您可以将结果事件绑定到可测试的观察者,而不是使用toBocking


虽然ToBlock在某些情况下很有用,但当您将事件绑定到testableObserver时,您会获得更多信息。

您可以使用MainScheduler.instance scheduler限制查询。试着移除它,看看会发生什么。这可能就是为什么你只能得到一个。在测试时,您需要将测试调度程序注入该节流阀

有几种不同的方法可以将正确的调度程序引入到您的模型中。根据您当前的代码,依赖项注入可以正常工作

struct SearchViewModelImpl: SearchViewModel {
    let query = PublishSubject<String>()
    let results: Observable<BookResult<[Book]>>

    init(searchService: SearchService, scheduler: SchedulerType = MainScheduler.instance) {
        results = query
            .distinctUntilChanged()
            .throttle(0.5, scheduler: scheduler)
            .filter({ !$0.isEmpty })
            .flatMapLatest({ searchService.search(query: $0) })
    }
}
此外,您可以将结果事件绑定到可测试的观察者,而不是使用toBocking


虽然ToBlock在某些情况下很有用,但是当您将事件绑定到testableObserver时,您会获得更多信息。

您可以使用MainScheduler.instance scheduler限制查询。试着移除它,看看会发生什么。这可能就是为什么你只能得到一个。在测试时,您需要将测试调度程序注入该节流阀。此外,您可以将结果绑定到观察者,然后检查这些事件,而无需执行let events=try!苏特。结果。采取2。托布洛克。今天你他妈的是对的,@JustinM!现在的问题是如何注入测试调度程序:\n请将此注释转换为答案,我将接受它:但是,除此之外,这只适用于第一种类型的测试,不适用于RxBlock。请给我几分钟时间,我将编写一个工作示例,并将其张贴在您使用MainScheduler.instance scheduler限制查询的文章中。试着移除它,看看会发生什么。这可能就是为什么你只能得到一个。在测试时,您需要将测试调度程序注入该节流阀。此外,您可以将结果绑定到观察者,然后检查这些事件,而无需执行let events=try!苏特。结果。采取2。托布洛克。今天你他妈的是对的,@JustinM!现在的问题是如何注入测试调度程序:\n请将此注释转换为答案,我将接受它:但是,除此之外,这只适用于第一种类型的测试,不适用于RxBlock。请给我几分钟时间,我将编写一个工作示例并发布它