我刚刚开始学习使用XCTest和xcode 7.2编写单元测试,并且我认为此Xcode不支持OCMock框架。我对这个框架一无所知。我现在只有XCTest Framework。我的问题是如何为单例对象编写案例。在这里,我使用了依赖注入的一些代码来制作属性和全部。
@property (nonatomic, strong) UIApplication *application;
- (UIApplication*)application
{
if (!_application)
{
_application = [UIApplication sharedApplication];
}
return _application;
}
- (IBAction)pushNotificationsSwitchWasToggled:(id)sender
{
UISwitch *toggleSwitch = sender;
if (toggleSwitch.on)
{
[self.application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
}
else
{
[self.application unregisterForRemoteNotifications];
}
}
测试
如果要测试以上方法
- (void)testToggleOnRegistersForPushNotifications_On
{
//given
SettingsViewController *sut = [[SettingsViewController alloc] init];
sut.application =[UIApplication sharedApplication];
//Here only one object is created ? not new right.
[sut.pushNotificationsSwitch setOn:YES];
//when
[sut pushNotificationsSwitchWasToggled:sut.pushNotificationsSwitch];
//here I am expecting code whether registerForRemoteNotificationTypes method is called or not.
}
1)在这里,当我们在任何地方使用单例时,仅创建对象一次。在测试用例中,我不想使用真正的
[UIApplication sharedApplication]
。我要测试一个假的或假的对象。2)我们如何确定是否注册了远程通知(通常如何确定是否调用方法?)。不使用
[UIApplication sharedApplication]
,您可以使用NSUSerDefault
的任何单例示例来解释我(提供输入并将结果与预期的进行比较。) 最佳答案
在测试中,您想注入其他东西来代替真正的UIApplication。只要满足您所需的方法,“其他”便可以是任何东西。我们甚至不必使用模拟对象框架。例如:
@interface MockApplication : NSObject
@property (nonatomic, assign, readonly) NSUInteger registerForRemoteNotificationTypesCount;
@property (nonatomic, strong, readonly) NSMutableArray *remoteNotificationTypes;
@property (nonatomic, assign, readonly) NSUInteger unregisterForRemoteNotificationsCount;
@end
@implementation MockApplication
- (instancetype)init
{
self = [super init];
if (self)
{
_remoteNotificationTypes = [[NSMutableArray alloc] init];
}
return self;
}
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types
{
self.registerForRemoteNotificationTypesCount += 1;
[self.remoteNotificationTypes addObject:@(types)];
}
- (void)unregisterForRemoteNotifications
{
self.unregisterForRemoteNotificationsCount += 1;
}
@end
然后在您的测试代码中:
MockApplication *mockApplication = [[MockApplication alloc] init];
sut.application = (id)mockApplication;
在测试结束时,您现在可以查询模拟应用程序以查看被调用的内容和参数。
一旦了解了这一原理,便可以通过使用诸如OCMock或OCMockito之类的模拟对象框架来节省时间。
我有一个截屏视频,显示了如何使用OCMockito模拟NSUserDefaults。实际上,它还不止如此,因为它涵盖了测试驱动开发:请参阅Objective-C TDD: How to Get Started