如何TDD UITableViewController(使用故事板)

时间:2014-04-20 11:55:08

标签: unit-testing tdd uitableview

我开始使用TDD并且无法测试一个简单的UITableViewController(使用故事板)。

对于我的模型NSArray中的每个元素,tableView应该有一行:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.sortedStories count];
}

我对此的测试是:

- (void)testTwoStoriesShouldLeadToTwoRowsInSectionZero
{
    _sut.sortedStories = [self arrayWithTwoStories];
    [_sut.tableView reloadData];

   XCTAssertEqual([_sut tableView:_sut.tableView numberOfRowsInSection:0], 2, @"The number of rows should match the number of stories");
}

我正在我的测试课中从我的故事板中初始化我的_sut:

- (void)setUp
{
    [super setUp];
    UIStoryboard *storyboard =
    [UIStoryboard storyboardWithName:@"Main_iPhone"
                              bundle:nil];

    _sut = [storyboard instantiateViewControllerWithIdentifier:
            @"MyTableViewController"];
}

如果我的生产代码中没有设置模型,则此工作完全正常。但是在我的UITableViewController的viewDidLoad方法中添加了七个故事的默认设置之后:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.sortedStories = [self sevenDefaultStories];
}

测试突然失败,说七点不等于两个'。 tableView似乎没有重新加载数据,虽然在更改模型后我的测试中有[_sut.tableView reloadData]

我做错了什么?

2 个答案:

答案 0 :(得分:0)

我找到了它:

虽然tableViewController是通过故事板等实例化的,但视图尚未加载!

当我'改变'我的模型时,viewDidLoad还没有被调用。但是,当我调用[_sut.tableView reloadData]时(应该确保,tableView会与我的模型同步),这导致完全相反:访问tableView使得必须加载视图,所以NOW finally {{在我的tableViewController上调用了1}}!所以我的模型再次改变,用默认值覆盖我的测试模型。

解决方法是将viewDidLoad添加到我的测试用例的顶部。这样可以确保在我的测试开始时已加载视图。

而且,就我而言,根本不需要调用[_sut view];,因为我只是直接测试dataSource方法,而不是实际的tableView。 N.B.:[_sut.tableView reloadData]仍然需要被调用,因为我的XCTAssertEqual()语句中的dataSource方法也触发了要加载的视图,如果尚未发生的话。

因此,工作测试用例如下所示:

[_sut view]

答案 1 :(得分:0)

在测试设置期间(我的首选解决方案):

[UIApplication sharedApplication].keyWindow.rootViewController = _sut; // Suck it UIKit

您也可以考虑:

[[UIApplication sharedApplication].keyWindow addSubview:_sut.view]; // Hax

请注意,UITableView可能无法呈现任何单元格,除非它已添加到视图层次结构中。同样,除非将UIViewController生命周期方法添加到视图控制器层次结构中,否则可能无法调用它们。我目前使用上面的“我的首选解决方案”,因为它完成了两者。