【问题标题】:CLLocationManager and unit testingCLLocationManager 和单元测试
【发布时间】:2013-02-03 00:28:20
【问题描述】:

我最近一直在尝试向我的代码中添加一些(逻辑)单元测试。我用Kiwi 设置了测试,我喜欢 BDD 风格和语法。

我现在的问题是我正在尝试测试一些依赖于CLLocationManager 发送正确locationManager:didUpdateToLocation:fromLocation: 的代码。但是,当我运行测试时,这从未发生过,大概是因为CLLocationManager 认为它没有被授权。作为记录,我已经向测试目标添加了一个 .gpx 文件并编辑了方案以使用该文件作为位置(在 Edit Scheme... -> 测试 -> 信息)。当我在模拟器中运行完整的应用程序时,相同的代码可以正常工作。知道如何获取(模拟)位置更新以在测试用例中发送吗?

【问题讨论】:

    标签: iphone ios cocoa cllocation ocunit


    【解决方案1】:

    使用依赖注入来指定您要使用的位置管理器。您可以:

    • 将其指定为初始化程序的参数(构造函数注入)
    • 将其设置为属性(setter 注入)

    如果可以的话,尝试使用构造函数注入。

    然后为了真正的使用,传入一个真正的 CLLocationManager。但是对于测试使用,提供一个可以触发发送所需方法的假,并带有预设的测试参数。通过删除对您的实际位置的任何引用,这也使您的测试具有确定性。

    【讨论】:

    • 我担心这是唯一的方法,但这意味着我需要对现有代码进行相当多的重构。持有 CLLocationManager 的类是单例的,所以如果我想使用initWithManager: 而不仅仅是init,我不能使用sharedController 类方法来获取实例。然后,您建议创建一个模拟CLLocationManager,拦截startUpdatingLocationstopUpdatingLocation,并以某种方式手动将CLLocation 实例和数组提供给locationManager:didUpdateLocations:?好痛啊……
    • 这个答案是正确的,但正如我在下面指出的,为了简单起见,我仍然决定采用不同的方法。
    • 单例是单元测试的祸根。还有另一种方式。将其公开为 setter 注入的属性,但让您的初始化程序设置一个合理的默认值——在这种情况下,是所需的单例。然后您的测试可以替换它。
    【解决方案2】:

    我最终采用了不同的方式:我将逻辑测试转换为应用程序测试,以便测试实际上与模拟器中的应用程序一起运行。这具有明确的优势,即我不必费力地让[NSBundle mainBundle]CLLocationManager 像在应用程序中一样工作。我更喜欢单独的逻辑测试的概念上的简洁性,但我认为仅仅为此重写代码是没有意义的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      相关资源
      最近更新 更多