在 RxSwift 中测试 UITableView.rx.itemSelected 回调

Posted

技术标签:

【中文标题】在 RxSwift 中测试 UITableView.rx.itemSelected 回调【英文标题】:Testing UITableView.rx.itemSelected callback in RxSwift 【发布时间】:2018-05-07 21:03:42 【问题描述】:

我有一个绑定到实例var myStrings: BehaviorRelay<[String]>的tableView,这样tableView中每个单元格的标签都设置为myStrings中每个字符串的值:

myStrings.bind(to: tableView.rx.items(cellIdentifier: cellReuseId, cellType: MyTableCell.self))  row, str, cell in
            cell.textLabel?.text = str
        .disposed(by: disposeBag)

我订阅了 tableView 上的项目选择。

tableView.rx.itemSelected.subscribe(onNext:  indexPath in
            let currentStr: String = try! self.tableView.rx.model(at: indexPath)
            self.delegate?.use(currentStr)
        ).disposed(by: disposeBag)

我将如何在单元测试中测试我订阅 itemsSelected 时的关闭?

【问题讨论】:

modelSelected代替itemSelected怎么样? 【参考方案1】:

如果您使用RxSwift,不确定为什么需要使用委托,但测试您所追求的一种方法是将您的表视图注入到您的代码中使用它的对象中 sn-p ,并且还创建一个符合您的表格视图单元格的委托的模拟对象(您要测试的订阅中的那个)。前者将允许您在单元测试用例中创建表格视图并以编程方式选择其中的单元格。然后,后者将允许您测试订阅中调用的委托方法是否使用正确的字符串调用。

要测试您的委托,请在单元测试中使用符合您委托协议的模拟对象,为您的方法设置“间谍”,然后针对该对象及其间谍回调运行断言:

class MockDelegateObject: TableViewCellDelegate 
    var stubUse: (() -> String)?

    // MARK: - TableViewCellDelegate
    func use(_ cellString: String) 
        stubUse?(cellString)
    


class MyTableViewTests: XCTestCase 
    func testCellString() 
        let testExpectation = expectation(description: #function)

        let expectedCurrentString = "Foo"

        // Create an instance of your mock object which conforms to your delegate; its spy method will get called with your cell text string when the delegate method is called in your subscription code
        let mockDelegateObject = MockDelegateObject()
        mockDelegateObject.stubUse =  cellString in
            XCTAssertEqual(expectedCurrentString, cellString)
            testExpectation.fulfill()
        

        // Initialize your table view and do whatever you need to do to add your table view to a window, view controller, etc.
        let tableView = MyTableView()
        let sut = MyTableViewOwningObject(tableView: tableView)

        // Set your object's delegate to be the mock delegate we've created which will receive messages from the subscription in your code
        sut.delegate = mockDelegateObject

        // Do whatever it is you need to do to kick off your table view data loading/displaying, ultimately calling
        sut.loadData()

        // Tell your table view to select whichever cell you want
        let firstIndexPath = IndexPath(row: 0, section: 0)
        tableView.selectRow(at: firstIndexPath, animated: false, scrollPosition: .none)
        tableView.delegate?.tableView?(self.tableView, didSelectRowAt: firstIndexPath)

        waitForExpectations(timeout: 0.001)
    

【讨论】:

以上是关于在 RxSwift 中测试 UITableView.rx.itemSelected 回调的主要内容,如果未能解决你的问题,请参考以下文章

使用 RxSwift 异步加载 UITableView 单元格

如何在 RxSwift 中观察 UITableView 点击/选择的先前值和当前值?

RxSwift、RxCocoa 和 UITableview

处理 UITableView 绑定中的连接错误(Moya、RxSwift、RxCocoa)

如何在 UITableView 的 RXswift 和 RXCocoa 中实现 tableview 单元格的内部?

RxSwift + RxRealm + RxCocoa 向 UITableView 插入行