如何使用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不是最好的解决方案,但看起来你想要实现一些全局组装访问。