我有一个我想要测试的方法:
- (void)openEmailFeedback
{
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setToRecipients:@"test@example.com"];
[controller setSubject:@""];
[controller setMessageBody:@"" isHTML:NO];
[self presentViewController:controller animated:YES completion:nil];
}
我尝试用
进行测试- (void)testOpenEmailFeedback
{
ViewController *vc = [[ViewController alloc] init];
// Create a partial mock of UIApplication
id mockMailComposeViewController = [OCMockObject mockForClass:[MFMailComposeViewController class]];
[[mockMailComposeViewController expect] setMailComposeDelegate:vc];
[[mockMailComposeViewController expect] setToRecipients:@[@"test@example.com"]];
[[mockMailComposeViewController expect] setSubject:@""];
[[mockMailComposeViewController expect] setMessageBody:@"" isHTML:NO];
[vc openEmailFeedback];
[mockMailComposeViewController verify];
[mockMailComposeViewController stopMocking];
}
但是我意识到mockMailComposeViewController远不是与该方法中的本地MFMailComposeViewController *控制器相同的变量。是否有可能如何访问方法中的局部变量" openEmailFeedback"在测试时?
答案 0 :(得分:3)
这个问题的标准答案是使用依赖注入模式。使用OCMock和部分模拟,还可以使用另一种模式。只需在类中创建一个具有依赖项和存根的工厂方法。在ViewController中:
- (MFMailComposeViewController *)createComposeViewController
{
return [[MFMailComposeViewController alloc] init];
}
- (void)openEmailFeedback
{
MFMailComposeViewController* controller = [self createComposeViewController];
controller.mailComposeDelegate = self;
// continue as normal...
在你的测试中:
- (void)testOpenEmailFeedback
{
ViewController *vc = [[ViewController alloc] init];
// Create a partial mock of UIApplication
id mockMailComposeViewController = [OCMockObject mockForClass:[MFMailComposeViewController class]];
[[mockMailComposeViewController expect] setMailComposeDelegate:vc];
[[mockMailComposeViewController expect] setToRecipients:@[@"test@example.com"]];
[[mockMailComposeViewController expect] setSubject:@""];
[[mockMailComposeViewController expect] setMessageBody:@"" isHTML:NO];
id vcPartialMock = [OCMockObject partialMockForObject:vc];
[[[vcPartialMock stub] andReturn:mockMailComposeViewController] createComposeViewController];
// continue as before...
答案 1 :(得分:0)
我通常使用这种模式来模拟我正在测试的方法中的本地创建的对象 -
MyClass *instance = [[MyClass alloc] init];
id mockMyClassObj = [OCMockObject mockForClass:[MyClass class]];
[[[mockMyClassObj stub] andReturn:instance] alloc];
然后在断言中 -
// Lets say I am testing for property 'whatever' being nil after calling the method I am testing
XCTAssertNil(instance.whatever, @"whatever should be nil");
以下是该代码的Xcode代码段 -
<#Class#> *<#instance#> = [[<#Class#> alloc] init];
id mock<#name#> = [OCMockObject mockForClass:[<#class#> class]];
[[[mock<#name#> stub] andReturn:<#instance#>] alloc];