我开始使用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]
。
我做错了什么?
答案 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
生命周期方法添加到视图控制器层次结构中,否则可能无法调用它们。我目前使用上面的“我的首选解决方案”,因为它完成了两者。