NSAssert([dateString isEqualToString:@"Three days,until 6:00 PM"],@"Date string should match expectation");
然而,由于应用程序是针对多种语言进行本地化的,同时我的开发人员也来自不同的地区,我的设备或模拟器可能会被设置为与测试所写的不同的区域设置.在这样的场景中,dateString的内容可能是这样的:
@"Drie dagen,tot 18:00" // the assertion fails @"Drei Tage,bis 18 Uhr" // the assertion also fails
这可能是也可能不是这些区域设置的正确日期符号,但是我的问题所在的部分是如何在底层代码使用Apple API时能够对特定区域进行测试.
[NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterShortStyle];
我很乐意在我的断言中用两种或更多种语言来覆盖,这样的东西:
[NSSomething actionToSetTheLocaleTo:@"en_US"]; dateString = ...; // the formatting NSAssert([dateString isEqualToString:@"Three days,@"match en_US"); [NSSomething actionToSetTheLocaleTo:@"nl_NL"]; dateString = ...; // the formatting NSAssert([dateString isEqualToString:@"Drie dagen,tot 18:00"],@"match nl_NL");
谁知道如何达到这个效果?
笔记:
>改变首选语言并不会削减它,还需要影响NSDateFormatter和NSNumberFormatter行为.
>因为这只是为了单元测试的目的,所以我会使用私有API来满足.然而,为了让其他人绊倒这个职位,公共API是首选.
>将自定义语言环境传递给每个日期或数字格式API可能是最后的考虑因素,但我发布了这个问题,希望避免回到这些极端措施.如果你知道这是唯一的解决方案,请提供一些参考,我将不再浪费时间
> Nice article by Ray Lillywhite on i18n and l10n
> NSHipster article on NSLocale
解决方法
事实证明,解决方案与类方法内部使用的“一样简单”为swizzling the methods:
beforeEach(^{ [NSBundle ttt_overrideLanguage:@"nl"]; [NSLocale ttt_overrideRuntimeLocale:[NSLocale localeWithLocaleIdentifier:@"nl_NL"]]; }); afterEach(^{ [NSLocale ttt_resetRuntimeLocale]; [NSBundle ttt_resetLanguage]; });
上面看到的ttt _…方法使用NSObject,NSLocale和NSBundle上的类别来检查运行时是否应该使用原始方法或返回其他内容.在编写测试时,这种方法无瑕疵,尽管技术上不使用任何私有API,但我强烈建议您仅在测试设置中使用此功能,而不是您提交给App Store进行审阅的任何内容.
In this gist you’ll find the Objective-C categories我添加到我的应用程序的测试目标来实现所需的行为.