如何使用Typhoon为Integration测试注入假,存根或模拟依赖项

我正在尝试使用KIF编写集成测试。 我的问题是:

如何为特定的视图控制器注入stubbed,mock或fake依赖?

每个使用依赖关系的视图控制器,如数据模型,http客户端,商店管理器等,都来自ModelAssembly,ApplicationAssembly,ManagerAssmebly。

在storyboard上,对于登录视图,我有一个键路径,包含值“loginViewController”。

创建视图控制器:

ViewControllersAssembly.h

@interface ViewControllersAssembly : TyphoonAssembly @property (nonatomic, strong) ModelAssembly *modelAssembly; - (id)loginViewController; @end 

ViewControllersAssembly.m

 @implementation ViewControllersAssembly - (UIViewController *)loginViewController { return [TyphoonDefinition withClass:[LoginViewController class] configuration:^(TyphoonDefinition *definition) { [definition injectProperty:@selector(userModel) with:[self.modelAssembly userModel]]; }]; 

}

UserModel有登录方法

 - (RACSingnal*)loginWithEmail:(NSString*)email password:(NSString*)password; 

现在在集成测试目标我有类似的类:

LoginTests.h

 @interface LoginTests : KIFTestCase @property (nonatomic, strong) UserModel *fakeUserModel; @end 

LoginTests.m

 @implementation LoginTests - (void)beforeAll { self.fakeDataModel = [self mockDataModel]; } - (void)testLogin { [self.fakeDataModel mockNextResponse:[RACSignalHelper getGeneralErrorSignalWithError:[[NSError alloc] initWithDomain:@"http://some.com" code:452 userInfo:nil]]]; [tester waitForViewWithAccessibilityLabel:@"loginScreen"]; [tester enterText:@"user@gmail.com" intoViewWithAccessibilityLabel:@"emailAdress"]; [tester enterText:@"asd123" intoViewWithAccessibilityLabel:@"password"]; [tester tapViewWithAccessibilityLabel:@"loginButton"]; [tester tapViewWithAccessibilityLabel:@"OK"]; // for example error code 542 we should display alert with message "User Banned" // now somehow check that UIAlertView localizedDescription was "User Banned" } - (FakeUserModel *)mockUserModel { ModelAssembly *modelAssembly = [[ModelAssembly assembly] activate]; TyphoonPatcher *patcher = [[TyphoonPatcher alloc] init]; [patcher patchDefinitionWithSelector:@selector(userModel) withObject:^id{ return [FakeUserModel new]; }]; [modelAssembly attachDefinitionPostProcessor:patcher]; return [modelAssembly userModel]; } 

FakeUserModel是覆盖UserModel类的类,为下一个被调用的请求添加了存根响应的可能性。

该解决方案不起作用。

我应该如何以及在哪里通过FakeUserModel?

1)我想访问注入的实例

2)注入的实例必须是FakeUserModel类型,它只在集成测试目标中。

3)我不想修改集成测试的生产代码。

unit testing

如果您希望使用测试double替换给定类的所有依赖项,从而与其协作者隔离地测试类,则这将是一个unit testing。 只需实例化一个测试实例,将您的测试双打(模拟,存根等)作为协作者传递。

集成测试

如果您希望使用测试双精度修补程序集中的一个或多个实例,为了使系统进入集成测试所需的状态,Typhoon提供了几种方法。

您可以按如下方式修补组件:

 MiddleAgesAssembly* assembly = [[MiddleAgesAssembly assembly] activate]; TyphoonPatcher* patcher = [[TyphoonPatcher alloc] init]; [patcher patchDefinitionWithSelector:@selector(knight) withObject:^id{ Knight* mockKnight = mock([Knight class]); [given([mockKnight favoriteDamsels]) willReturn:@[ @"Mary", @"Janezzz" ]]; return mockKnight; }]; [assembly attachPostProcessor:patcher]; Knight* knight = [(MiddleAgesAssembly*) factory knight] 

有关此方法的更多信息,请参阅用户指南的“ 集成测试”部分。

模块化

或者,您可以模块化您的程序集,并使用子类或替代实现进行激活,该实现提供某些类的另一个实现,例如:

 UIAssembly *uiAssembly = [[UIAssembly new] activateWithCollaboratingAssemblies:@[ [TestNetworkComponents new], //<--- Patched for testing [PersistenceComponents new]]; SignUpViewController* viewController = [uiAssembly signUpViewController]; 

有关此方法的更多信息,请参阅用户指南的模块化部分 。

如果要修补故事板使用的程序集并使用Plist集成进行初始化,则可以通过调用以下命令使该程序集默认为:

 [yourAssembly makeDefault]; 

你可以通过调用以下方法在测试用例中获得这个程序集:

 [yourAssembly defaultAssembly]; 

之后,您可以轻松修补一些定义。 在测试开始之前让你的程序集默认是很重要的,所以也许app delegate会是一个很好的地方。 这是probalby不是最好的解决方案,但看起来你想要实现一些全局组装访问。