如何为单例XCTest Framework xcode 7编写测试用例



我刚刚开始学习使用XCTest和xcode 7.2编写单元测试,我认为这个xcode不支持OCMock框架。我对这个框架一无所知。我现在只知道XCTest框架。这里我的问题是如何为单例对象编写用例。在这里,我使用了一些带有依赖注入的代码来创建属性和所有内容。

@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) 这里,当我们在任何地方使用singleton时,对象只创建一次。在测试用例中,我不想使用真正的[UIApplication sharedApplication]。我想要一个假人或假物体来测试。

2) 我们如何判断远程通知是否注册(通常情况下,如何判断方法是否被调用?)。不是用[UIApplication sharedApplication],你可以用NSUSerDefault的任何单例例子来解释我(给出输入并将结果与预期结果进行比较)

在测试中,您希望注入其他东西来代替真正的UIApplication。"其他东西"可以是任何东西,只要它能回答你需要的方法。我们甚至不必使用mock对象框架。例如:

@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;

在测试结束时,您现在可以查询mockApplication,查看调用了什么,以及使用了什么参数。

一旦您理解了这一原理,就可以通过使用OCMock或OCMockito等mock对象框架来节省时间。

我有一个屏幕截图,展示了如何使用OCMockito模拟NSUserDefaults。事实上,它不止于此,因为它涵盖了测试驱动开发:请参阅Objective-C TDD:How to Get Started

最新更新