XCTest does not work when calling [NSBundle mainBundle]

I have code that calls [NSBundle mainBundle]at some point, mainly for reading / setting preferences. When I use the unit test method, the test fails because the test mainBundle does not contain a file.

This is a known issue that Apple will not fix, as they believe this is not a bug :

The essence of their answer is that XCTest works correctly, returning its own main package instead of the test target package.

Previously, our code base used a category override in a class method NSBundle +mainBundleto get around this. But this is dangerous because the behavior of overriding an existing method in a category is undefined .

If the name of the method declared in the category is the same as the method in the source class, or the method in another category in the same class (or even in the superclass), the behavior is undefined for which the method is used at runtime.

Actually Xcode warns you about this:

A category implements a method, which will also be implemented by its main class.

So what is the proper method to solve this problem?

+3
source share
1 answer

The easiest and cleanest way to solve this problem is to partially mock the NSBundle class in your unit tests to return [NSBundle bundleForClass:[self class]]when you call [NSBundle mainBundle].

-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

.

[]

+7

Source: https://habr.com/ru/post/1657697/


All Articles