RxSwift PublishSubject 单元测试

Posted

技术标签:

【中文标题】RxSwift PublishSubject 单元测试【英文标题】:RxSwift PublishSubject unit test 【发布时间】:2021-11-20 01:51:37 【问题描述】:

这是我的视图模型

import Foundation
import RxSwift

class CitiesViewModel 
    let service: CityServiceProvider
    var cities: PublishSubject<[CityDetail]> = PublishSubject()
    let errorMessage: PublishSubject<String> = PublishSubject()
    
    init(service: CityServiceProvider) 
        self.service = service
    
    
    func getCities(completion: (() -> ())? = nil)  
        service.getCities  result in
            switch result 
            case .success(let response):
                self.cities.onNext(response.cityList)
            case .failure(let error):
                self.errorMessage.onNext(error.localizedDescription)
            
            completion?()
        
    

我只是想知道如何在调用getCities() 之后测试cities 是否具有价值而errorMessage 没有价值(我将在单元测试中使用模拟服务)

这是我的单元测试

    func testSuccessfulResult() 
        let expectation = self.expectation(description: #function)
        let service = MockCityServiceWithSuccessResponse()
        let viewModel = CitiesViewModel(service: service)

        viewModel.getCities(completion: 
            expectation.fulfill()
        )
        
        viewModel.cities.subscribe  details in
            // This body will never execute
            guard let details = details.element else 
                XCTFail("Details is empty")
                return
            
            XCTAssertTrue(details.count > 0, "Load details successfully")
        .disposed(by: DisposeBag())
        
        wait(for: [expectation], timeout: 2)
    

【问题讨论】:

【参考方案1】:

您正在订阅cities值已经发出并且期望得到满足之后。将您的订阅移至 getCities 调用之前,您应该会看到成功。

还有:

cities 不应该是 var。所有主题应始终为let 常量。 您的视图模型不应公开主题。将主题设为私有并改为公开 Observable。 (否则,任何人都可以将价值观推送到主题中。)

【讨论】:

以上是关于RxSwift PublishSubject 单元测试的主要内容,如果未能解决你的问题,请参考以下文章

RxSwift 中的 PublishSubject 和 PublishRelay 有啥区别?

RxSwift - PublishSubject - 忽略错误并继续订阅(不要处置)

正在处理 RxSwift PublishSubject

RxSwift:将 PublishSubject 绑定到多个按钮并接收发送者

在 RxSwift PublishSubject 上完成后订阅最后一个值

如何在按钮点击时观察 PublishSubject