我有一个使用本地化字符串的iPhone iOS4.1应用程序。我刚刚开始使用SenTestingKit构建单元测试。我已经能够成功测试许多不同类型的值。
我无法正确测试任何使用NSLocalizedString调用的代码,因为当代码在我的LogicTests目标中运行时,我的所有NSLocalizedString调用都只返回字符串键。
我已将Localizable.strings文件添加到LogicTests目标。
我的问题是:如何配置我的LogicTests目标,以便调用NSLocalizedString将返回本地化字符串而不是字符串键。
答案 0 :(得分:10)
这个问题让我发疯,但我能够让NSLocalizedString
表现出来。
zoul是对的,如果你在逻辑测试中将mainBundle打印到控制台,它就不是包含你的Localizable.strings文件的bundle。每次运行单元测试时,您都需要有条件地重新定义NSLocalizedString
。我是按照以下步骤完成的:
Preprocessor Macros
构建设置中。我的代码中只有一个位置我需要重新定义NSLocalizedString
,因此我能够将以下代码放在与该类对应的标题中。如果您在多个地方遇到此问题,我建议将以下代码放在标题中并#include
- 将其放在您需要的位置(我尝试使用.pch文件,但它无效逻辑测试)。无论如何,将它放在使用NSLocalizedString
的类的标题中的某处:
#ifdef LOGIC_TESTS
#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleWithIdentifier:@"YOUR_IDENTIFIER"] localizedStringForKey:(key) value:@"" table:nil]
#endif
将YOUR_IDENTIFIER
替换为应用套装的捆绑标识符(位于Info.plist
文件中,密钥为CFBundleIdentifier
)。这假定您已在逻辑测试目标中将LOGIC_TESTS
定义为预处理器宏 。
编辑:奇怪的是,一旦我删除了一些调试代码,此解决方案就停止了工作。看起来你必须欺骗Xcode加载捆绑包。以下是:
NSString *path = @"path_to_main_bundle";
NSBundle *bundle = [NSBundle bundleWithPath:path];
NSLog(@"bundles: %@", [NSBundle allBundles]);
运行主要目标时path_to_main_bundle
为== [[NSBundle mainBundle] bundlePath]
的位置。只需在gdb中记录一次,或在app delegate上使用NSLog
即可获取路径。它应该看起来像/Users/YOUR_USER_NAME/Library/Application Support/iPhone Simulator/4.1/Applications/UUID_LOTS_OF_LETTERS_AND_NUMBERS_HERE/App.app
。
我将该代码放在我的一个逻辑测试类的setUp调用中。不,我不知道为什么我必须记录allBundles才能使它工作,所以任何有线索的人都请告诉我!
答案 1 :(得分:7)
我能够在单元测试的设置中使用以下代码来使用NSLocalizedString
- (void)setUp
{
[super setUp];
NSString *bundlePath = [[NSBundle bundleForClass:[self class]] resourcePath];
[NSBundle bundleWithPath:bundlePath];
}
答案 2 :(得分:4)
我遇到了同样的问题,并且,感谢@kevboth,我通过向 YourUnitTests-Prefix.pch 添加两行来解决它:
#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleForClass:[self class]] localizedStringForKey:(key) value:@"" table:nil]
答案 3 :(得分:2)
Swift的快捷方式: 这是一个简单的版本,可以扩展到不同的用例(例如使用tableNames)。
public func NSLocalizedString(key: String, referenceClass:AnyClass) -> String
{
let bundle = NSBundle(forClass: referenceClass)
return NSLocalizedString(key, tableName:nil, bundle: bundle, comment: "")
}
此全局方法可以放在单个.swift文件中,也可以放在类范围之外的其他位置。 像这样使用它:
NSLocalizedString("YOUR-KEY", referenceClass: self)
答案 4 :(得分:1)
也许NSLocalizedString
只能在应用程序测试中运行?这是一个在主包上调用localizedStringForKey:value:table:
的宏。也许+[NSBundle mainBundle]
会在测试目标中返回iffy?
答案 5 :(得分:0)
在我看来,最简洁的解决方案只是在你的octest包中加入Localizable.strings
。
答案 6 :(得分:0)
Swift 4.1 - Xcode 9.3
Localizable.strings(en)
"TEXT_TO_LOCALIZE" = "Hello!";
Localizable.strings(es)
"TEXT_TO_LOCALIZE" = "Hola!";
XCTestCase
class AppTestCase: XCTestCase {
func testLocalize() {
let localizedText = "TEXT_TO_LOCALIZE".localized(for: reference)
print(localizedText) // "Hello!" or "Hola!"
}
}
extension String {
public func localized(for aClass: AnyClass) -> String {
let bundle = Bundle(for: aClass)
return NSLocalizedString(self, tableName: nil, bundle: bundle, comment: "")
}
}
extension XCTestCase {
var reference: AnyClass {
return type(of: self)
}
}