【问题标题】:How to write test cases for singleton XCTest Framework xcode 7如何为单例 XCTest Framework xcode 7 编写测试用例
【发布时间】:2016-04-12 21:58:04
【问题描述】:

我刚开始学习使用 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) 这里当我们在任何地方使用单例时,对象只会被创建一次。在测试用例中,我不想使用真正的 [UIApplication sharedApplication] 。我想要一个虚拟对象或假对象进行测试。

2)我们如何判断远程通知是否注册(一般如何判断方法是否被调用?)。不是[UIApplication sharedApplication],您可以用NSUSerDefault 的任何单例示例向我解释(提供输入并将结果与​​预期进行比较。)

【问题讨论】:

    标签: ios objective-c xctest


    【解决方案1】:

    在您的测试中,您想要注入其他东西来代替真正的 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;
    

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

    一旦你理解了这个原理,那么你就可以通过使用诸如OCMockOCMockito等模拟对象框架来节省时间。

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

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 2020-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-04
      • 1970-01-01
      相关资源
      最近更新 更多