George
George

Reputation: 3708

Unit testing crash at cellForRowAtIndexPath

I have a simple tableview with some rows. Each row is a custom cell with an xib file. I have implemented the delegate and datasource and its working fine when I run the app. This is the way I have implemented it.

class P: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        registerCell()
    }

    func registerCell() {
        self.tableView.register(UINib(nibName: "PCell", bundle: nil), forCellReuseIdentifier: "cell")
    }

    #number of rows implemented here

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PCell
        cell.titleLabel.text = "Great"
        return cell
    }
}

This code works fine.

The problem is when I try to unit test the tableView I am facing problem. This is how I am unit testing

class MockPController: PController {

}

class PControllerTests: XCTestCase {
    let mpc = MockPController()

    //THIS IS WORKING
    func testNumberOfSections() {
        mpc.viewDidLoad()
        XCTAssertEqual(mpc.numberOfSections(in: mpc.tableView), 5)
    }

    func testTitleForPCells() {
        mpc.viewDidLoad()
        var cell = mpc.tableView(mpc.tableView, cellForRowAt: IndexPath(row: 0, section: 1)) as! PCell
        //THE APP CRASHES AT THE CELLFORROWATINDEXPATH FUNCTION IN ACTUAL CODE - HERE "let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! PCell"
        //APP CRASHES HERE SAYING "Could not cast value of type 'Project.PCell' to 'ProjectTests.PCell'
    }
}

On getting this app crash I added a override function for registerCell() in MockPController, so the new MockPController becomes

class MockPController: PController {
    override func registerCell() {
        self.tableView.register(PCell.self, forCellReuseIdentifier: "cell")
    }
}

After adding this override function I am not getting crash at the dequeueReusableCell, but now app crashes saying that the outlet variable titleLabel is nil.

So I guess it is not getting the right instance of the cell because of the override registerCell() function. But without it also app crashes.

What am I doing wrong?

I searched google but I am not getting any result.

Upvotes: 1

Views: 722

Answers (1)

ryancrunchi
ryancrunchi

Reputation: 475

You seem trying to test UITableView's cellForRowAt: method. Which is not what you want. You want to test your PCell class. To do so, instanciate a PCell with superclass init init(style:reuseIdentifier:). Then call a method of your own like pcell.doSomethingThatSetTheTitle() and assert that the title of your cell is what you expect.

EDIT:

func testTitleForPCells() {
    let cell = PCell(style: .default, reuseIdentifier: "anything")
    let model = Model(title: "FOO")
    cell.setMyModel(model)
    XCTAssertEqual(cell.titleLabel.text, model.title)
}

Upvotes: 1

Related Questions