【问题标题】:XCTest fails when calling [NSBundle mainBundle]调用 [NSBundle mainBundle] 时 XCTest 失败
【发布时间】:2023-03-19 18:20:02
【问题描述】:

我有一些代码在某些时候调用[NSBundle mainBundle],主要是为了读取/设置首选项。当我对该方法进行单元测试时,测试失败,因为测试的 mainBundle 不包含该文件。

这是a known issue,Apple 不会修复它,因为他们认为它是not a bug

他们回复的要点是 XCTest 通过返回它自己的主包而不是测试目标的包来正常工作。

以前我们的代码库在NSBundle+mainBundle 类方法上使用类别覆盖来解决这个问题。但是this is dangerous because the behaviour of overriding an existing method in a category is undefined

如果一个类别中声明的方法的名称与原始类中的方法名称相同,或者同一类(甚至超类)上的另一个类别中的方法名称相同,则行为未定义至哪个方法实现在运行时使用。

实际上 Xcode 会警告你:

类别正在实现一个方法,该方法也将由其主类实现

那么,解决这个问题的正确方法是什么?

【问题讨论】:

  • XCTest 没有并且从未返回+[NSBundle mainBundle] 的测试包。 (与 OCUnit 相同。)我不确定它的想法来自哪里——链接页面不再可用,所以我看不到它是否有进一步的参考——但据我所知,我们从未告诉过其他任何人。

标签: ios unit-testing nsbundle xctest ocmock


【解决方案1】:

解决此问题的最简单和最干净的方法是在您的单元测试中部分模拟 NSBundle 类,以便在您调用 [NSBundle mainBundle] 时返回 [NSBundle bundleForClass:[self class]]

您可以将其放入您的 -setup 方法中,以便为您的整个测试类模拟它:

static id _mockNSBundle;

@implementation MyTests

- (void)setUp
{
  [super setUp];

  _mockNSBundle = [OCMockObject niceMockForClass:[NSBundle class]];
  NSBundle *correctMainBundle = [NSBundle bundleForClass:self.class];
  [[[[_mockNSBundle stub] classMethod] andReturn:correctMainBundle] mainBundle];
}

@end

干净整洁。

[Source]

【讨论】:

  • 既然 mockNSBundle 是静态的,为什么不使用静态的 +setup 方法呢?
  • 在 Swift 中怎么做?
  • @Ramis 在 Swift 中你无论如何都不会使用 OCMock。相反,您需要重构代码以使用代码注入,然后在您的测试类中继承 NSBundle 并覆盖该函数。
猜你喜欢
  • 2016-09-12
  • 2016-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
相关资源
最近更新 更多