Reputation: 1275
I'm using Kiwi to write tests for an app. I am trying to verify that the cell returned from tableView:cellForRowAtIndexPath:
has the correct values set after the call. I've done a unch of different variations of this with no luck:
describe(@"tableView:cellForRowAtIndexPath:", ^{
it(@"Should return a cell with proper label values",
^{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
id mockTableView = [UITableView mock];
id mockCell = [UITableViewCell mock];
[mockTableView stub:@selector(dequeueReusableCellWithIdentifier:forIndexPath:) andReturn:mockCell withArguments:any(), indexPath];
[mockCell stub:@selector(label1)
andReturn:[[UILabel alloc] init]];
[mockCell stub:@selector(label2)
andReturn:[UILabel alloc]];
CustomTableViewCell *cell = (CustomTableViewCell *)
[dataSource tableView:mockTableView
cellForRowAtIndexPath:indexPath];
[[cell.label1.text should]
equal:@"abc"];
[[cell.label2.text should] equal:@"xyz"];
});
});
The actual method looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:kCustomCellReuseIdentifier
forIndexPath:indexPath];
CustomObject *obj = [self objAtIndexPath:indexPath];
[self setupCell:cell withObj:obj];
return cell;
}
- (void)setupCell:(
CustomTableViewCell *)cell withObj:(CustomObject *)obj
{
cell.label1.text = @"abc";
cell.label2.text = @"xyz";
}
It seems to get caught on cell.label1
being nil
- however, I do stub those earlier.
Any thoughts on how to actually write this test are welcome.
Upvotes: 0
Views: 369
Reputation: 737
As you are testing UIKit classes, have you seen the Kiwi wiki page that states the following?
Specs that perform operations on UIKit classes (e.g. UILabels) will probably crash weirdly if they are run under anything other than an Application Test. To learn more about how to set up an Application Test target, check out the official Apple docs.
Sounds like you may want to make sure that the test target is an Application Test, as opposed to a Logic Test.
Upvotes: 0
Reputation: 366
If you instantiate the CustomTableViewController programatically via the storyboard, you will not need to set the labels on the custom cell if they are hooked up as outlets. However, it looks like you might be building the cell UI programatically, so just initialize the labels on the mocked CustomCell like so before running the test action:
describe(@"CustomTableViewControllerTest", ^{
__block CustomTableViewController *controller;
beforeEach(^{
controller = [[CustomTableViewController alloc] initWithStyle:UITableViewStylePlain];
controller.tableView = [[UITableView alloc] init];
});
describe(@"tableView:cellForRowAtIndexPath:", ^{
it(@"Should return a cell with proper label values", ^{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
CustomTableViewCell *mockCell = [[CustomTableViewCell alloc] init];
mockCell.label1 = [[UILabel alloc] init];
mockCell.label2 = [[UILabel alloc] init];
[controller.tableView stub:@selector(dequeueReusableCellWithIdentifier:forIndexPath:) andReturn:mockCell withArguments:any(), indexPath];
CustomTableViewCell *cell = (CustomTableViewCell *)[controller tableView:controller.tableView cellForRowAtIndexPath:indexPath];
[[cell.label1.text should] equal:@"abc"];
[[cell.label2.text should] equal:@"xyz"];
});
});
});
Remember, not everything needs to be a mock. In fact i believe it is better to mock as little as possible when writing tests because it keeps your objects accountable for behaving properly after creation. I ran this locally, and it passes.
Upvotes: 0