16

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

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

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

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

4

7 回答 7

10

这个问题让我发疯,但我能够NSLocalizedString表现得很好。

zoul 是对的,如果您在逻辑测试中将 mainBundle 打印到控制台,则它与包含您的 Localizable.strings 文件的包不同。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
    

替换YOUR_IDENTIFIER为您的应用程序包的包标识符(在您的Info.plist文件中找到,键是CFBundleIdentifier)。这假定您在 Logic Tests 目标中定义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 中记录一次或NSLog在您的应用程序委托上使用来获取路径。它应该看起来像/Users/YOUR_USER_NAME/Library/Application Support/iPhone Simulator/4.1/Applications/UUID_LOTS_OF_LETTERS_AND_NUMBERS_HERE/App.app.

我将该代码放在我的一个逻辑测试类的 setUp 调用中。不,我不知道为什么我必须记录 allBundles 才能使其工作,所以任何有线索的人,请告诉我!

于 2010-10-11T18:59:49.497 回答
7

我能够在我的单元测试设置中使用以下代码使用 NSLocalizedString

- (void)setUp
{
    [super setUp];

    NSString *bundlePath = [[NSBundle bundleForClass:[self class]] resourcePath];
    [NSBundle bundleWithPath:bundlePath];
}
于 2012-06-07T00:00:56.990 回答
4

我遇到了同样的问题,感谢@kevboth,我通过在YourUnitTests-Prefix.pch中添加两行来解决它:

#undef NSLocalizedString
#define NSLocalizedString(key, comment) [[NSBundle bundleForClass:[self class]] localizedStringForKey:(key) value:@"" table:nil]
于 2012-04-10T07:19:41.000 回答
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)
于 2016-01-18T09:58:02.593 回答
1

也许NSLocalizedString只能在应用程序测试中工作?localizedStringForKey:value:table:这是一个在主包上调用的宏。也许+[NSBundle mainBundle]在测试目标中返回一些不确定的东西?

于 2010-10-10T07:20:04.087 回答
0

在我看来,最干净的解决方案只是Localizable.strings在你的 octest 包中包含一个。

于 2012-08-31T20:14:02.847 回答
0

斯威夫特 4.1 - Xcode 9.3

Localizable.strings (zh)

"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)
   }
} 
于 2018-03-30T19:32:35.820 回答