TableView isSelected 场景的单元测试 Swift

Dra*_*ner 4 unit-testing ios swift

我有一个简单的场景和 tableView。

我需要选择 3 个单元格,即使我滚动它也会保持这样。我可以选择 1、2 或 3 个单元格,但不能选择 4 个或更多。当我选择 4 个单元格时,什么都不会发生。如果有 3 个选定的单元格,并且我单击其中之一,则应取消选择我选择的单元格。到目前为止,一切都很好。感谢@vadian 的帮助,我可以按如下方式实现此目的。但我整天尝试为这种情况编写单元测试,但无法处理它。我决定向帮助社区寻求帮助,但仍然找不到方法。

问题是:如何针对这种情况用一种好的方法编写单元测试?

    /// My Model ///

struct Item: Codable {
    
    let name: String
    let image: String
   
    var isSelected = false
   
    enum CodingKeys: String, CodingKey {
        case name = "name"
        case image = "image"
      
    }
}

// MARK: - UITableViewDelegate
extension ViewController: UITableViewDelegate {

let items = [Item]() // fetched from network, there is item objects inside it.

// MARK: - UITableViewDataSource
extension ItemViewModel: UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Food", for: indexPath) as! FoodTableViewCell
        
        let item = self.items[indexPath.row]

        cell.isSelected = item.isSelected
      
        return cell
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

zey*_*tin 6

当然,您可以为 tableView 操作编写许多单元测试,但我同意 Matt 的观点“这应该很简单”。您的 ViewModel 需要根据“单独关注”原则进行处理,否则需要重构。我假设您将所有逻辑移至 ViewModel 中,然后您可以编写如下单元测试。

import Foundation

class YourViewControllerTest: XCTestCase {
    
    var viewModel: ItemViewModel!
    fileprivate var fetcher: MockItemFetcher!
    
    var tableView: UITableView!
    
    override func setUp() {
        super.setUp()
        
        fetcher = MockItemFetcher()
        viewModel = ItemViewModel(fetchable: fetcher)
        
    }
    
    override func tearDown() {
        viewModel = nil
        fetcher = nil
        tableView = nil
        super.tearDown()
    }
    
    /// test the one cell can be selectable or not
    func test_did_select_a_cell() {
        
        let items = [Item(name: "", image: "",)]
        // given
        fetcher.items = items
        viewModel.fetchItems()
        
        let viewController = YourViewController()
        let tableView = UITableView()
        viewController.viewModel = viewModel
        
        // when
        viewController.tableView(tableView, didSelectRowAt: IndexPath(row: 0, section: 0))
        
        // then
        XCTAssertNotNil(willBeSelected)
    }
Run Code Online (Sandbox Code Playgroud)