调用 [NSBundle mainBundle] 时 XCTest 失败

XCTest fails when calling [NSBundle mainBundle]

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

这是a known issue, that Apple won't fix as they consider it is not a bug:

the gist of their reply is that XCTest is working correctly by returning it’s own main bundle instead of the bundle of the test target.

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

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime.

实际上 Xcode 警告你:

Category is implementing a method which will also be implemented by its primary class

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

解决此问题的最简单和最干净的方法是在调用 [NSBundle mainBundle] 时将单元测试中的 NSBundle class 部分模拟为 return [NSBundle bundleForClass:[self class]]。 =15=]

您可以将它放在您的 -setup 方法中,以便在您的整个测试中模拟它 class:

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]