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

时间:2018-05-07 21:03:42

标签: ios swift rx-swift reactivex rx-cocoa

我有一个绑定到实例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时的闭包?

1 个答案:

答案 0 :(得分:0)

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

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

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)
    }
}