2015-03-11 5 views
3

У меня есть код, который вызывает в какой-то момент [NSBundle mainBundle], в основном для чтения/установки предпочтений. Когда я тестирую метод, тест терпит неудачу, потому что mainBundle теста не содержит файл.Ошибка XCTest при вызове [NSBundle mainBundle]

Это a known issue, что компания Apple не исправит, как они считают это not a bug:

суть их ответа в том, что XCTest работает правильно, вернув свою собственную основную связку вместо расслоения целевой тест.

Ранее наш кодовая использовал категорию переопределение по методу +mainBundle класса NSBundle «s работать вокруг этого. Но this is dangerous because the behaviour of overriding an existing method in a category is undefined.

Если имя метода, объявленного в категории такой же, как метод в исходном классе, или метода в другой категории по одному классу (или даже суперкласса), его поведение не определено, как к реализация этого метода используется во время выполнения.

На самом деле Xcode предупреждает вас об этом:

Категория реализует метод, который также будет реализован его основной класс

Итак, что такое правильный способ для решения этой проблемы ?

+0

XCTest * не * и никогда не вернулся тестовый пакет для '+ [NSBundle mainBundle]'. (То же самое с OCUnit.) Я не уверен, откуда появилась идея о том, что она появилась - связанная страница больше недоступна, поэтому я не вижу, есть ли у нее дополнительные ссылки, но насколько я знаю, мы никогда не говорили любой другой. –

ответ

7

Самый простой и чистый способ устранить эту проблему - частично издеваться над классом NSBundle в своих модульных тестах, чтобы вернуть [NSBundle bundleForClass:[self class]] при вызове [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 

красивых и чистых.

[Source]

+1

Как mockNSBundle статично, почему бы не использовать статический + метод установки? – OliverM

+2

Как это сделать в Swift? – Ramis

+0

@ Ramis Ну в Swift вы все равно не будете использовать OCMock. Вместо этого вам нужно будет реорганизовать ваш код для использования инъекции кода, а затем в вашем тестовом классе вы будете подклассифицировать NSBundle и переопределить функцию. – KPM