unit test cellForRowAtIndexPath when using storyBoards

喜欢而已 提交于 2019-12-12 08:14:28

问题


If I'm dequeuing a cell from an identifier in a storyboard, how in a unit testing way can I call cellForRowAtIndexPath and not have the cell be nil?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    MyCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCustomCell];

    cell.guestNameText.text = self.details.guestName;

    return cell;
}

Not working, put a break point above after dequeReusableCell is called and cell is nil:

ETA: UPDATED WORKING CODE TO PASS THE TEST:

- (void)setUp {

    [super setUp];
    _detailVC_SUT = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]
     instantiateViewControllerWithIdentifier:kDetailsVC];
    _myService = [OCMockObject niceMockForClass:[MyService class]];
    _detailVC_SUT.service = _myService;
}


- (void)test_queryForDetailsSucceeded_should_set_cell_text_fields {

    [_detailVC_SUT view]; // <--- Need to load the view for this to work
    Details *details = [DetailsBuilder buildStubDetails];
    [_detailVC_SUT queryForDetailsSucceededWithDetails:details];

    [self getFirstCellForGuestName];
}

- (void)getFirstCellForGuestName {

    MyCustomTableViewCell *guestNameCell = (MyCustomTableViewCell*)[_detailVC_SUT tableView:_detailVC_SUT.detailsTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];

    expect(guestNameCell.guestNameText.text).to.equal(@"Mark");
}

回答1:


Here is how I test table views and their cells. The key here is to call beginAppearanceTransition on view controller in order to load it from the storyboard.

class MyTests: XCTestCase {
  var viewController: UIViewController!

  override func setUp() {
    super.setUp()

    let storyboard = UIStoryboard(name: "MyStoryboard", bundle: nil)
    viewController = storyboard.instantiateViewControllerWithIdentifier("myViewControllerId")
    viewController.beginAppearanceTransition(true, animated: false)
  }

  override func tearDown() {
    super.tearDown()

    viewController.endAppearanceTransition()
  }


  func testShowItemsFromNetwork() {
    //
    // Load the table view here ...
    //

    let tableView = viewController.tableView

    // Check the number of table rows

    XCTAssertEqual(3, tableView.dataSource?.tableView(tableView, numberOfRowsInSection: 0))

    // Check label text of the cell in the first row

    let indexPath = NSIndexPath(forRow: 0, inSection: 0)
    let cell = tableView.dataSource?.tableView(tableView, cellForRowAtIndexPath: indexPath)
    XCTAssertEqual("Test cell title", cell!.textLabel!.text)
  }
}



回答2:


The table view has a frame of CGRect.zero when it tries to call cellForRow(at:). As a result, cellForRow(at:) returns nil. In order to test it I did the following inside your test function:

func testCellForRow_AtZero_ReturnsTaskCell() {
    let mockTableView = UITableView(frame: CGRect(x: 0, y: 0, width: 320, height: 480), style: .plain)

     mockTableView.dataSource = dataSource
     mockTableView.register(YourTableViewCell.self, forCellReuseIdentifier: String(describing: YourTableViewCell.self))

     //The reload is also necessary
     mockTableView.reloadData()

     let cell = mockTableView.cellForRow(at: IndexPath(row: 0, section: 0))

     XCTAssertTrue(cell is YourTableViewCell)
}

Don't forget that in your dataSource you should have a value for the Indexpath(row: 0, section: 0). Otherwise the test would fail.



来源:https://stackoverflow.com/questions/17864605/unit-test-cellforrowatindexpath-when-using-storyboards

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!