如何在RxSwift单元测试中模拟UITableView行选中操作
如何在RxSwift驱动的UITableViewController单元测试中模拟行选中操作?
你遇到的问题核心是直接调用传统UITableView代理方法并不适配RxSwift的事件绑定逻辑,才导致了unrecognized selector异常。我来帮你拆解问题并给出可行的解决方案:
问题根源
你在代码里用的是tableView.rx.itemSelected这个RxSwift封装的事件流处理行选中,而非传统的UITableViewDelegate方法。RxSwift会为UITableView设置内部代理对象监听事件,你的FeedViewController并没有被设置为tableView的delegate——直接调用tableView(_:didSelectRowAt:)不仅会触发找不到方法的错误,也根本不会触发Rx的事件流。
正确的模拟方式
要触发RxSwift绑定的行选中事件,你需要直接向tableView.rx.itemSelected这个Observable发送事件,而非调用代理方法。
修正后的测试代码
func test_ViewController_PresentsDetailView_On_Selection() { let indexPath = IndexPath(row: 0, section: 0) sut.start().subscribe().disposed(by: rx_disposeBag) let viewControllers = sut.navigationController.viewControllers let vc = viewControllers.first as! FeedViewController // 确保视图已完成加载,Rx绑定逻辑已初始化完成 vc.loadViewIfNeeded() // 直接向Rx的itemSelected事件流发送选中信号 vc.tableView.rx.itemSelected.onNext(indexPath) XCTAssertNotNil(sut.navigationController.presentedViewController) }
额外注意事项
还有个容易忽略的细节:你需要确保viewModel.posts已经有数据返回,否则selectedPost中的withLatestFrom操作符会因为没有数据源而无法触发后续的跳转逻辑。建议在测试时mock你的FeedService,返回测试用的Post数据:
// 定义Mock服务 class MockFeedService: HasFeedService { func getFeed() -> Single<[Post]> { // 返回一条测试数据,确保posts流有内容 return Single.just([Post(id: "test_id", title: "Test Post")]) } } // 在测试初始化时注入Mock服务 let mockDependency = FeedViewModel.Dependency(feedService: MockFeedService()) // 后续将这个mockDependency传入ViewModel初始化
这样就能保证选中行时,selectedPost能正确拿到对应的Post对象,进而触发视图控制器的跳转逻辑,你的断言也能正常验证。
内容的提问来源于stack exchange,提问作者Harry Blue
相关产品推荐
相关产品推荐

