I have a ViewController that contains a tableView. Since I need to keep the code well covered with tests, I need to write a test for [tableView:cellForRowAtIndexPath]
There are two separate concepts, the tableView and the dataSource. TableView is just a view, and has cells which are views as well. DataSource is the data provider of the tableView, and the only component responsible for data.
In your test example, you call a tableView.cellForRowAtIndexPath
function in order to get a cell, in a specific indexPath. Based on official docs, this function will return nil if the cell is not visible. So this function should be used, only when you know that the table is visible.
In your example, you are trying to test that your table will load data properly. When referring to data, data source is the first thing that should come to your mind. So you need to test that the dataSource will bind the correct information to your cells. As a result you call controller.tableView.dataSource(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0)))
There are a number of things that could be going wrong here. Some possibilities:
tableView
itself could be nil.tableView:cellForRowAtIndexPath:
method. That used to be necessary if no cells were available for reuse, but these days a properly configured table will instantiate new cells as needed, and IIRC instantiating your own can cause a crash.Step 1: Go to Identity Inspector of your view controller in storyboard and give it a storyboard id. Ex: "vcIdentifier"
Step 2: You have get the instance of your storyboard in Unit test
Step 2 : Instantiate your view controller via storyboard instance from step 2
Step 3 : Get access to your table view from the viewcontroller and pass it to 'cellForRowAt' method in your test. Please see below a sample code:
let storyboard = UIStoryboard(name: "Main", bundle:nil)
let newsViewController: UITableViewController = storyboard.instantiateViewController(identifier: "vcIdentifier")
return newsViewController.tableView
For me, (Swift 3) I had to call the cellForRow datasource cellForRowAt function instead of accessing straight from the tableView.cellForRow function
//this
let cell = controller.tableView(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0))
//instead of this
let cell = controller.tableView.cellForRow(at: IndexPath(row: 0, section: 0))