2

我正在寻找一种“最佳实践”/“低测试摩擦”的方式来对我的基础 AppDelegate 类中的视图控制器进行基于状态的测试。目前,当在类的方法中发生某些事情时,下面提供了一种简单的方法来存根我自己的 UIViewController(使用 ocmock)。

-(FirstViewController *)getFirstViewController
{
    if (self.viewController1)
    { return self.viewController1; }

    self.viewController1 = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];

    return self.viewController1;
}

我的第一个问题 - 这是一种有效的方法来存根/注入我自己的模拟视图控制器进行测试吗?(似乎工作得很好,但我不确定这是否是专业人士今天进行基于状态的测试的方式)

我的下一个问题 - 像这样在内存中保留 1 个视图控制器副本是否有效(在应用程序的整个生命周期内只从头开始创建一次)?

**注意-我会依赖注入它,但我的 init 已经足够大,只需要注入导航控制器和标签栏控制器,所以遗憾的是,这不是这个大类的选项

4

3 回答 3

1

依赖注入不需要你通过 init 方法注入所有的依赖。首选是有原因的,但这是另一个讨论。

您可以简单地向您的类添加一个 -setFirstViewController: 方法。您将在测试中使用该方法来注入您的模拟。如果您不喜欢在您的应用程序中使用该方法,您可以使用测试代码中的类别添加该方法。

于 2012-03-18T18:47:15.950 回答
1

如果它是根视图控制器,则应将其设置为应用程序委托的属性:

@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];
}
于 2012-03-23T06:34:07.527 回答
0

对于这种测试,我会让它像你一样,嗯,略有不同。

第一视图控制器的第一个延迟加载被封装在一个属性中。

在 .h 文件中

@interface AppDelegate {
    FirstViewController *viewController1_;
}

然后

@property (nonatomic, readonly) FirstViewController viewController1;

在 .m 文件中

- (FirstViewController *)viewController1 {
    if (!viewController1_) {
        viewController1_ = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil];
    }

    return viewController1_;
}

第二 - 如果我想注入一个模拟对象,我在我的测试代码中使用 KVC

[appDelegateUnderTest setValue:mockViewController forKey:@"viewController1_"];

问候,

于 2012-03-20T22:27:03.347 回答