测试代码:
id dataControllerMock = [OCMockObject mockForClass:[RAMImsakyaDataController class]];
[[[dataControllerMock expect] andReturn:dataControllerMock] alloc];
(void)[[[dataControllerMock expect] andReturn:dataControllerMock] init];
[[[dataControllerMock stub] andReturn:@"30.06 , 50.67"] getLocationTitle];
[self.viewController viewDidLoad];
XCTAssertTrue([self.viewController.title isEqualToString:@"30.06 , 50.67"], @"View controller title is wrong");
[dataControllerMock verify];
问题是,dataControllerMock导致失败与"意外的方法调用:getLocationTitle"!我确实存根了这个方法。即使我把存根改成期望值,也是一样的。当我在viewDidLoad内部断点时,模拟已经如预期的那样存在,但它不识别getLocationTitle方法。
更新:这里是viewDidLoad代码NSString *location = [self.dataController getLocationTitle];
if (location == nil) {
self.title = @"إمساكية رمضان ١٤٣٥ هـ";
} else {
self.title = [NSString stringWithFormat:@"إمساكية رمضان ١٤٣٥ هـ (توقيت %@)", location];
}
为什么不采用不同的方法并使用部分模拟呢?
RAMImsakyaDataController* realObject = [RAMImsakyaDataController new];
id partialObject = [OCMockObject partialMockForObject:realObject];
[[[partialObject stub] andReturn:@"30.06 , 50.67"] getLocationTitle];
[partialObject viewDidLoad]; // Method under test
XCTAssertTrue([partialObject.title isEqualToString:@"30.06 , 50.67"], @"View controller title is wrong");
我发现尝试模拟alloc会导致困难的行为。
编辑
// In MyViewController
- (RAMImsakyaDataController*)dataController {
if (!_dataController) {
_dataController = [[RAMImsakyaDataController alloc] init];
}
return _dataController;
}
Then partial mock the VC and replace this method with one that returns your partially mocked data controller.
我的猜测是OCMock未能正确模拟数据控制器的+alloc
方法,所以你的视图控制器使用真正的数据控制器而不是模拟。
我有一个困难的时间模拟对象创建。我最终所做的不是试图模拟+alloc
,而是将可测试性存根放在我想要测试的对象上,这些对象创建了它们的依赖关系,然后我可以使用被测试对象的部分模拟来覆盖对象创建。如:
@implementation ViewController
- (void)init {
...
_dataController = [self newDataController];
...
}
- (DataController *)newDataController {
return [[DataController alloc] init];
}
@end
然后在我的test
ViewController *underTest = [ViewController alloc];
id mockUnderTest = [OCMockObject partialMockForObject:underTest];
id mockDataController = [OCMockObject niceMockForClass:[DataController class]];
[[[mockUnderTest stub] andReturn:[mockDataController retain]] newDataController];
underTest = [underTest init];