我想创建一个集成测试,该测试显示某个操作会导致显示模态视图控制器。故事板设置有2个viewcontrollers,一个带有自定义ViewController类,第二个带有默认的UIViewController类和标题“second”。 segue设置为模态,标识符为“modalsegue”。在模拟器中运行应用程序非常出色,但我在定义正确的测试时遇到了很多麻烦。
ViewController.m:
@implementation ViewController
- (IBAction)handleActionByPerformingModalSegue {
[self performSegueWithIdentifier:@"modalsegue" sender:self];
}
@end
测试:
- (void)testActionCausesDisplayOfSecondViewController {
ViewController * vc =
[[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil]
instantiateViewControllerWithIdentifier:@"ViewController"];
[vc handleActionByPerformingModalSegue];
STAssertEquals(vc.presentedViewController.title, @"second",
@"Title of presented view controller should be second but is %@",
vc.presentedViewController.title, nil);
}
在以下输出中运行测试结果:
2013-06-23 17:38:44.164 SeguesRUs[15291:c07] Warning: Attempt to present <UIViewController: 0x7561370> on <ViewController: 0x7566590> whose view is not in the window hierarchy!
SeguesRUsTests.m:33: error: -[SeguesRUsTests testActionCausesDisplayOfSecondViewController] : '<00000000>' should be equal to '<9c210d07>': Title of presented view controller should be second but is (null)
我做错了什么?有没有一种简单的方法可以避免第一条消息?
答案 0 :(得分:1)
正如错误消息所指出的那样,问题是您尝试在UIViewController
上查看其视图不在UIWindow
层次结构中。
解决问题的最简单方法:
- (void)testExample {
//
// Arrange
// Storyboard
//
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
//
// Arrange
// View Controller
//
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:@"ViewController"];
[UIApplication sharedApplication].keyWindow.rootViewController = viewController;
//
// Act
//
[viewController performSegueWithIdentifier:@"ModalSegue" sender:nil];
//
// Assert
//
XCTAssertEqualObjects(viewController.presentedViewController.title, @"Second");
}
答案 1 :(得分:0)
这是我的工作。 假设我连接了手动触发的segue(DocumentsDetailVC)的DocumentsVC。 下面是我的设置然后我测试1.存在segue然后2.我强制视图控制器(在我的情况下我发布通知)触发其performSegueWithIdentifier并拦截prepareForSegue方法以查看是否所有内容都是新的视图控制器(DocumentsDetailVC)已设置。这包括方法调配。
我没有使用OCHamcrest / OCMockito进行单元测试,并且我的所有segue都是以“Segue”([self appDelegate] segueIdentifierForClass:[SomeClass class]])添加的目标视图控制器命名的。
- (void)setUp
{
[super setUp];
_isPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
realPrepareForSegue = @selector(prepareForSegue:sender:);
testPrepareForSegue = @selector(documentsBrowserTest_prepareForSegue:sender:);
UIStoryboard *storyboard = nil;
if (_isPad) {
storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
}
else {
storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPad" bundle:nil];
}
UINavigationController *navController = [storyboard instantiateInitialViewController];
self.sut = (DocumentsBrowserVC *)navController.topViewController;
[self.sut view];
}
- (void)test_DocumentsDetailsVCSegueConnected
{
if (_isPad == FALSE) {
STAssertNoThrow([self.sut performSegueWithIdentifier:[[self appDelegate] segueIdentifierForClass:[DocumentsDetailVC class]] sender:self], @"DocumentsDetailVC should be connected");
}
}
- (void)test_providerDidSelectPathLevelObject_triggersDocumentsDetailsVCSegueSectionIdFile
{
[DocumentsBrowserTest swapInstanceMethodsForClass:[DocumentsBrowserVC class]
selector:realPrepareForSegue
andSelector:testPrepareForSegue];
[[NSNotificationCenter defaultCenter] addObserver:self.sut selector:@selector(providerDidSelectPathLevelObject:) name:ProviderDidSelectPathLevelObjectNotification object:nil];
// when
PathLevelObject *plo = self.pathLevelObjects[SectionIdFile][4];
NSDictionary *userInfo = @{OBJECT_KEY : plo , BROWSER_AREA_KEY : @(DocumentsFolder)};
[[NSNotificationCenter defaultCenter] postNotificationName:ProviderDidSelectPathLevelObjectNotification object:nil userInfo:userInfo];
// then
if (_isPad == FALSE) {
assertThat(NSStringFromClass([objc_getAssociatedObject(self.sut, storyboardSegueKey) class]), is(equalTo(@"UIStoryboardPushSegue")));
assertThatBool([[objc_getAssociatedObject(self.sut, storyboardSegueKey) destinationViewController] isKindOfClass:[DocumentsDetailVC class]], is(equalToBool(TRUE)));
assertThat(objc_getAssociatedObject(self.sut, senderKey), is(equalTo(self.sut)));
}
else {
assertThatInteger(self.sut.detailViewController.browsingArea, is(equalToInteger(DocumentsFolder)));
assertThat(self.sut.detailViewController.pathLevelObject, is(equalTo(plo)));
}
[[NSNotificationCenter defaultCenter] removeObserver:self.sut];
[DocumentsBrowserTest swapInstanceMethodsForClass:[DocumentsBrowserVC class]
selector:realPrepareForSegue
andSelector:testPrepareForSegue];
}