Проверка соединения IBOutlet с OCMock

Я хочу проверить с помощью модульных тестов, что все IBoutlets в моем классе контроллера правильно подключены в файле NIB. Я хотел бы сделать это с OCMock - хотя я знаю, что могу просто утверждать, что переменные контроллеров не являются nil после загрузки СИБ. Это скорее вопрос общего понимания того, как работает этот процесс - насколько я понимаю, это тоже должно работать.

СИБ OnOffSwitchCell имеет в качестве владельца файла OnOffSwitchCellController, Это мой метод испытаний:

- (void) testIBOutletCellIsWiredToXib {
    id mockController = [OCMockObject mockForClass:[OnOffSwitchCellController class]];
    [[mockController expect] awakeAfterUsingCoder:OCMOCK_ANY];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"cell"];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"thelabel"];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"theswitch"];

    NSArray* nibContents = [guiBundle loadNibNamed:@"OnOffSwitchCell"
                                             owner:mockController
                                           options:nil];
    assertThat(nibContents, isNot(nil));
    assertThatInt([nibContents count], is(equalToInt(1)));
    assertThat([nibContents objectAtIndex:0], is(instanceOf([OnOffSwitchCell class])));

    [mockController verify];
}

guiBundle существует и проверено как действительный объект NSBundle.

Из того, что я понимаю loadNibNamed:owner:options: произойдет десериализация объектов в NIB, вызовите awakeAfterUsingCoder: а затем установить выходы по телефону setValue:forKey: для каждого.

Я вставил еще три утверждения, чтобы убедиться, что загруженный NIB на самом деле содержит правильные объекты - они проходят нормально, когда я вставляю экземпляр реального контроллера. Но когда я использую макет, как показано выше, он даже не заходит так далеко. Вместо этого тест завершается с этим:

 Тестовый пример '-[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib]' запущен.
 2011-01-14 10:48:35.364 GTMTest[67797:903] *** Завершение работы приложения из-за необработанного исключения "NSInternalInconsistencyException",
     причина: 'OCMockObject[OnOffSwitchCellController]:
              Вызван неожиданный метод: awakeAfterUsingCoder: 
    ожидается: setValue: forKey: @ "cell"
    ожидается: setValue: forKey: @ "thelabel"
    ожидается: setValue: forKey: @ "theswitch" '
*** Вызов стека при первом броске:
(
    0   CoreFoundation                      0x00e3dbe9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00f925c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00e3db21 -[Повышение NSException] + 17
    3   GTMTest                             0x0001a049 -[OCMockObject handleUnRecordedInvocation:] + 322
    4   GTMTest                             0x00019aca -[OCMockObject forwardInvocation:] + 77
    5   CoreFoundation                      0x00daf404 ___forwarding___ + 1124
    6   CoreFoundation                      0x00daef22 _CF_forwarding_prep_0 + 50
    7   UIKit                               0x0062394a UINibDecoderDecodeObjectForValue + 2438
    8   UIKit                               0x00624693 -[UINibDecoder decodeObjectForKey:] + 398
    9   UIKit                               0x0053cf43 -[UIRuntimeConnection initWithCoder:] + 212
    10  UIKit                               0x0053d4b1 -[UIRuntimeEventConnection initWithCoder:] + 64
    11  UIKit                               0x006239e4 UINibDecoderDecodeObjectForValue + 2592
    12  UIKit                               0x006232dc UINibDecoderDecodeObjectForValue + 792
    13  UIKit                               0x00624693 -[UINibDecoder decodeObjectForKey:] + 398
    14  UIKit                               0x0053c200 -[UINib instantiateWithOwner: параметры:] + 804
    15  UIKit                               0x0053e081 -[NSBundle(UINSBundleAdditions) loadNibNamed: владелец: опции:] + 168
    16  GTMTest                             0x000140dc -[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib] + 503
    17  GTMTest                             0x000041f3 -[SenTestCase invokeTest] + 163
    18  GTMTest                             0x0000479a -[GTMTestCase invokeTest] + 146
    19  GTMTest                             0x00003e90 -[SenTestCase executeTest] + 37
    20  GTMTest                             0x00002f3d -[GTMIPhoneUnitTestDelegate runTests] + 1413
    21  GTMTest                             0x000028fb -[GTMIPhoneUnitTestDelegate applicationDidFinishLaunching:] + 197
    22  UIKit                               0x00347253 -[UIApplication _callInitializationDelegatesForURL: полезная нагрузка: приостановлено:] + 1252
    23  UIKit                               0x0034955e -[UIApplication _runWithURL: полезная нагрузка: запускОриентация:statusBarStyle:statusBarHidden:] + 439
    24  UIKit                               0x00348ef0 -[UIApplication _run] + 452
    25  UIKit                               0x0035542e UIApplicationMain + 1160
    26  GTMTest                             0x00003500 main + 104
    27  GTMTest                             0x0000273d начало + 53
    28???                                 0x00000002 0x0 + 2)
прекращение вызова после выброса экземпляра 'NSException'

Так что жалуется на призыв awakeAfterUsingCoder: как неожиданный, хотя я явно ожидал этого.

Я также попытался удалить это ожидание и заменить макет на хороший макет, который не будет сообщать о лишних вызовах методов, но затем он все еще прерывается и сообщает setValue:forKey: не вызывается.

Что мне здесь не хватает?

2 ответа

Вы пробовали запустить это в главном системном потоке? Вы не можете создавать экземпляры классов UIKit из основного потока. Не уверен, как это делает GTM, но с помощью GHUnit вы можете поместить в класс тестового примера следующее:

- (BOOL)shouldRunOnMainThread {
    /* Tell GHUnit to run on a separate thread */
    return YES;
}

Вы не можете делать какие-либо визуальные вещи в модульных тестах. Представления никогда не загружаются. Кроме того, вам не нужно проверять, что awakeAfterUsingCoder вызывается. Это вещи Apple. Обычно ваши юнит-тесты должны проверять только вашу логику. Вы можете смело предположить, что awakeAfterUsingCoder вызывается из init, потому что это код Apple. Вам просто нужно убедиться, что ваши методы вызываются

Другие вопросы по тегам