使用 OCMock 对本地对象或依赖注入进行单元测试?
unit test local objects or dependency injection with OCMock?
正在尝试为以下功能创建简单测试:
-(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];
});
}
我可以通过依赖注入将其拆分成块,但不知道如何以任何一种方式编写正确的测试。此示例的最佳做法是什么?
您想要测试什么?您的方法中发生了 3 件事:
CustomVC
已通过 name
创建。
CustomVC
嵌入在导航控制器中。
- 导航控制器显示在
self.vc
。
您可以编写一个测试来检查整个流程:
- (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];
}
此代码检查您的方法中发生的所有事情 - 一个方法被调用时带有特定参数,这些参数中的第一个是仅嵌入 CustomVC
的导航控制器,并且此 CustomVC
设置了 name
。显然,我假设可以从外部设置测试 class 上的 vc
属性,并且可以读取 CustomVC
上的 name
。如果没有,测试其中的某些部分可能会更棘手。
就我个人而言,我不会对此进行单元测试。我将单独测试 CustomVC
的初始化,并将整个演示文稿置于 UI 测试之下。
如果一切都清楚,请告诉我!
—
旁注:我是凭记忆在手机上写的,所以代码中可能会有小错误。当我有机会用Xcode检查它时,我会更新它。
正在尝试为以下功能创建简单测试:
-(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];
});
}
我可以通过依赖注入将其拆分成块,但不知道如何以任何一种方式编写正确的测试。此示例的最佳做法是什么?
您想要测试什么?您的方法中发生了 3 件事:
CustomVC
已通过name
创建。CustomVC
嵌入在导航控制器中。- 导航控制器显示在
self.vc
。
您可以编写一个测试来检查整个流程:
- (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];
}
此代码检查您的方法中发生的所有事情 - 一个方法被调用时带有特定参数,这些参数中的第一个是仅嵌入 CustomVC
的导航控制器,并且此 CustomVC
设置了 name
。显然,我假设可以从外部设置测试 class 上的 vc
属性,并且可以读取 CustomVC
上的 name
。如果没有,测试其中的某些部分可能会更棘手。
就我个人而言,我不会对此进行单元测试。我将单独测试 CustomVC
的初始化,并将整个演示文稿置于 UI 测试之下。
如果一切都清楚,请告诉我!
—
旁注:我是凭记忆在手机上写的,所以代码中可能会有小错误。当我有机会用Xcode检查它时,我会更新它。