Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Test for TableView isSelected Scenario Swift

I have a simple scenario and tableView.

I need to select 3 cells and and even I scroll it will be stay like. I can select 1, 2 or 3 cells but not 4 or more.When I select 4 cells nothing should happen. If there are 3 selected cells and I click one of them the cell which I selected should be deselected. So far so good. Thanks to @vadian help I can make this happen as below. But I tried all day writing unit test for this scenario but could not handle it.. I decided to ask help community and still could not find a way..

Question is: How can I write unit test with a nice approach for this scenario ?

    /// 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
    }
  }
}
like image 625
DrainOpener Avatar asked Sep 14 '25 09:09

DrainOpener


1 Answers

Of course, you can write many unit tests for tableView actions but I agree with Matt in terms of "this should be simple". Your ViewModel needs to be handled according to "Separate Concern" principles otherwise it needs to be refactored. I assume you move all logic into ViewModel then you can write a unit test as below.

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)
    }
like image 179
zeytin Avatar answered Sep 16 '25 23:09

zeytin