繁体   English   中英

在Objective C单元测试中模拟系统日期和位置的最佳实践

[英]Best Practice for mocking system date and Location in Objective C unit tests

我正在尝试使用TDD方法在Objective C中编写一个类。 该类基本上应该实现该协议。

@protocol SeasonService <NSObject>

-(t_Season)currentSeason;

@end

t_Season只是冬季,春季,夏季和秋季的一个枚举。

假设我有一个实现上述伪代码的类

@implementation SeasonServiceImpl

    - (t_Season)currentSeason
    {
        // Get Date
        int month = [self currentMonth];

        // Get Latitude
        float latitude = [self currentLatitude];

        // work out the season based on month and latitude 
        // (i.e, Northern or Southern hemisphere)
        return season;
    }
}

我可以通过使用类别来公开currentMonthcurrentLatitude方法来测试上面的公共方法,然后使用OCMock进行局部模拟。 至少让我测试我的代码实现,以确定它是基于日期和位置的季节。

1)对我来说,使用类别扩展来有效地将两个私有方法转换为公共方法似乎是一种代码气味。 2)它没有测试我是否正确获取位置。

那么我将如何对此进行编码以便我可以测试我是否正确获取当前位置? 我的意思是,这是最好的方法,有一个不同的指定init方法,它接受一个CLLocationManager的实例。 那可能是一个模拟的实例,或者是代码在生产中运行的真实实例? 此外, currentSeason方法是否应该更改为currentSeasonForDate:NSDate

这种问题的传统解决方案是依赖注入 ,它有助于推动关注点分离 SeasonService的工作是根据纬度和月份确定它是什么季节。 确定/存储纬度和月份应该应该是其他类的责任。

根据系统的要求,可以通过构造参数或方法参数来实现。 无论哪种方式,您都可以直接模拟特定月份或纬度,而不是诉诸类别技巧。

构造函数注入:

- initWithLatitudeProvider:id<LatitudeProvider> latitudeProvider
          andMonthProvider:id<MonthProvider> monthProvider { 
    // set ivars or properties
}

- (t_Season)currentSeason
{
    // Get Date
    int month = [[self monthProvider] currentMonth];

    // Get Latitude
    float latitude = [[self latitudeProvider] currentLatitude];

    // work out the season based on month and latitude 
    // (i.e, Northern or Southern hemisphere)
    return season;
}

或方法参数注入:

- (t_Season)currentSeasonAtLatitude:(float)latitude inMonth:(int)month
{
    // work out the season based on month and latitude 
    // (i.e, Northern or Southern hemisphere)
    return season;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM