如何在iOS 5运行时为基于状态的测试存根/注入视图控制器?
我正在寻找一种“最佳实践”/“低测试摩擦”的方式来对基于AppDelegate类的视图控制器进行基于状态的测试。目前,下面提供了一种简单的方法来存储我自己的UIViewController(使用ocmock),当它发生在类的方法内部时。如何在iOS 5运行时为基于状态的测试存根/注入视图控制器?
-(FirstViewController *)getFirstViewController
{
if (self.viewController1)
{ return self.viewController1; }
self.viewController1 = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
return self.viewController1;
}
的第一个问题我有这个-Is来,踩灭/注入我自己的模拟视图控制器用于测试的有效方法是什么? (似乎工作很好,但我不知道这是如何专业人士如何进行基于状态的测试今天)
我有下一个问题 - 是否有效保持视图控制器的1副本像这样(只从头开始为应用程序的生命创建一次)?
**注 - 我的依赖注入这一点,但我的init已经足够大,只是注射的导航控制器和标签栏控制器,所以这不是这个大类的选择黯然
如果它的根视图控制器,你应该让你的应用程序委托的属性:
@interface MyAppDelegate : NSObject <UIApplicationDelegate>
@property(retain)FirstViewController *firstViewController;
@end
@implementation MyAppDelegate
@synthesize firstViewController;
...
@end
除非你正在测试的方法是你初始化firstViewController
的方法,你不需要任何种类的延迟加载方法。只要让应用程序的委托在您的测试,创建FirstViewController
一个实例,并将其分配给您的委托财产,并定义测试:如果你想要模拟出任何你就是控制器
-(void)testSomething {
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
FirstViewController *firstViewController = [[FirstViewController alloc] init];
appDelegate.firstViewController = firstViewController;
// test some app delegate method
...
}
测试中,你可以做到这一点,以及:
-(void)testSomething {
MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
id mockController = [OCMockObject mockForClass:[FirstViewController class]];
appDelegate.firstViewController = mockController;
[[mockController expect] someControllerMethod];
// test some app delegate method
...
[mockController verify];
}
依赖注入并不需要你通过init方法注入所有依赖关系。有理由为什么这是首选,但这是另一个讨论。
您可以简单地将-setFirstViewController:方法添加到您的类中。你会在你的测试中使用该方法来注入你的模拟。如果你不喜欢你的应用程序中的方法,你可以在测试代码中使用一个类别添加方法。
对于这种测试,我会让它像你一样,略有不同。
第一个视图控制器的延迟加载封装了一个属性。
在.h文件中
@interface AppDelegate {
FirstViewController *viewController1_;
}
然后
@property (nonatomic, readonly) FirstViewController viewController1;
在.m文件
- (FirstViewController *)viewController1 {
if (!viewController1_) {
viewController1_ = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
}
return viewController1_;
}
2阶如果我想注入模拟对象,我用KVC在我测试代码
[appDelegateUnderTest setValue:mockViewController forKey:@"viewController1_"];
问候,
公平一点 - 但如果我删除此方法,并做基本的setter注入如何做有关游戏瓦特/我的问题的第二部分时,新起来的这些依赖AppDelegate的? – 2012-03-18 22:12:38
您仍然可以将lazy-init保存在上面包含的getter中。只要确保在你的测试中你打电话给我第一次调用getter之前建议的setter。 – 2012-03-19 15:52:08