Trying to create simple test for following function:
-(void)presentWithString:(NSString *)name
{
CustomVC *customVC = [[CustomVC alloc] initWithName:name];
UINavigationController *nav = [[UINavigationController alloc] init];
nav.viewControllers = @[customVC];
dispatch_async(dispatch_get_main_queue(), ^{
[self.vc presentViewController:nav animated:YES completion:nil];
});
}
I can split this into chunks with dependency injection, but don't know how to write proper test either way. What would be the best practice for this example?
What do you want to test? There are 3 things happening in your method :
CustomVC
is created with name
passed.CustomVC
is embedded inside navigation controller.self.vc
.You can write a test that checks the whole flow :
- (void)testPresentWithString_shouldPresentCustomVC_withPassedName {
// Arrange
NSString *expectedName = @”name”;
XCTestExpectation *exp = [self expectationWothDescription:@”presentVC called”];
TestClass *sut = [[TestClass alloc] init];
id vcMock = OCMClassMock([UIViewController class]);
sut.vc = vcMock;
OCMExpect([vcMock presentViewController:OCM_ANY animated:YES completion:nil]).andDo(^(NSInvocation *invocation) {
UINavigationController *nav = nil;
[invocation getArgument:&nav atIndex:2];
CustomVC *custom = nav.viewControllers.firstObject;
// Assert
XCTAssertNotNil(nav);
XCTAssertTrue([nav isKindOfClass:[UINavigationController class]]);
XCTAssertEqual(nav.viewControllers.count, 1);
XCTAssertNotNil(custom);
XCTAssertTrue([custom isKindOfClass:[CustomVC class]]);
XCTAssertEqual(custom.name, expectedName);
[exp fulfill];
});
// Act
[sut presentWithString:expectedName];
// Assert
[self waitForExpectationsWithTimeout:1 handler:nil];
OCMVerifyAll(vcMock);
// Cleanup
[vcMock stopMocking];
}
This code checks everything that happens in your method - that a method got called with specific arguments, that the first of these arguments was a navigation controller with only CustomVC
embedded and that this CustomVC
had name
set. Obviously I’ve made assumptions that vc
property on tested class can be set from outside and that the name
on CustomVC
can be read. If not, it may be trickier to test some parts of this.
Personally I wouldn’t unit test this. I would test the initialization of CustomVC
separately, and put the whole presentation under a UI test.
Let me know if everything is clear!
—
Side note : I wrote this on mobile from memory, so there might be small mistakes in the code. I will update it when I have a chance to check it with Xcode.