单元测试使用NSLocalizedString的iPhone代码

时间:2010-09-30 17:18:15

标签: iphone unit-testing nslocalizedstring

我有一个使用本地化字符串的iPhone iOS4.1应用程序。我刚刚开始使用SenTestingKit构建单元测试。我已经能够成功测试许多不同类型的值。

我无法正确测试任何使用NSLocalizedString调用的代码,因为当代码在我的LogicTests目标中运行时,我的所有NSLocalizedString调用都只返回字符串键。

我已将Localizable.strings文件添加到LogicTests目标。

我的问题是:如何配置我的LogicTests目标,以便调用NSLocalizedString将返回本地化字符串而不是字符串键。

7 个答案:

答案 0 :(得分:10)

这个问题让我发疯,但我能够让NSLocalizedString表现出来。

zoul是对的,如果你在逻辑测试中将mainBundle打印到控制台,它就不是包含你的Localizable.strings文件的bundle。每次运行单元测试时,您都需要有条件地重新定义NSLocalizedString。我是按照以下步骤完成的:

  1. 我们需要一种方法来判断我们何时处于逻辑测试目标中,因此将LOGIC_TESTS添加到逻辑测试目标的Preprocessor Macros构建设置中。
  2. 我的代码中只有一个位置我需要重新定义NSLocalizedString,因此我能够将以下代码放在与该类对应的标题中。如果您在多个地方遇到此问题,我建议将以下代码放在标题中并#include - 将其放在您需要的位置(我尝试使用.pch文件,但它无效逻辑测试)。无论如何,将它放在使用NSLocalizedString的类的标题中的某处:

    #ifdef LOGIC_TESTS
    #undef NSLocalizedString
    #define NSLocalizedString(key, comment) [[NSBundle bundleWithIdentifier:@"YOUR_IDENTIFIER"] localizedStringForKey:(key) value:@"" table:nil]
    #endif
    
  3. 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)
   }
}