I'm trying to write integration tests using KIF. My question is:
How to inject stubbed, mock or fake dependency for particular view controller?
Each view controller using dependencies like a data model, http client, store manager etc. comes from ModelAssembly, ApplicationAssembly, ManagerAssmebly.
On storyboard, for login view i have a key path, containing value "loginViewController".
Creating view controllers:
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 have method to login
- (RACSingnal*)loginWithEmail:(NSString*)email password:(NSString*)password;
Now in integration tests target i have class like:
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 is class that override UserModel class, adding possibility to stub response for next called request.
that solution not is not working.
How and where i should pass FakeUserModel?
1) i'd like to have access to injected instance
2) injected instance must be of type FakeUserModel, which is only in integration tests target.
3) i don't want to modify production code for integration tests.