Проверка соединения IBOutlet с OCMock - PullRequest
1 голос
/ 14 января 2011

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

NIB 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 на самом деле содержит правильные объекты - они проходят нормально, когда я вставляюЭкземпляр настоящего контроллера.Но когда я использую макет, как показано выше, он даже не заходит так далеко.Вместо этого тест дает сбой с этим:

 Test Case '-[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib]' started.
 2011-01-14 10:48:35.364 GTMTest[67797:903] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
     reason: 'OCMockObject[OnOffSwitchCellController]:
              unexpected method invoked: awakeAfterUsingCoder:<UINibDecoder: 0x500e800> 
    expected:   setValue:<OCMAnyConstraint: 0x4c718e0> forKey:@"cell"
    expected:   setValue:<OCMAnyConstraint: 0x4c71ce0> forKey:@"thelabel"
    expected:   setValue:<OCMAnyConstraint: 0x4c71ed0> forKey:@"theswitch"'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00e3dbe9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00f925c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00e3db21 -[NSException raise] + 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:options:] + 804
    15  UIKit                               0x0053e081 -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] + 168
    16  GTMTest                             0x000140dc -[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib] + 503
    17  GTMTest                             0x000041f3 -[SenTestCase invokeTest] + 163
    18  GTMTest                             0x0000479a -[GTMTestCase invokeTest] + 146
    19  GTMTest                             0x00003e90 -[SenTestCase performTest] + 37
    20  GTMTest                             0x00002f3d -[GTMIPhoneUnitTestDelegate runTests] + 1413
    21  GTMTest                             0x000028fb -[GTMIPhoneUnitTestDelegate applicationDidFinishLaunching:] + 197
    22  UIKit                               0x00347253 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1252
    23  UIKit                               0x0034955e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
    24  UIKit                               0x00348ef0 -[UIApplication _run] + 452
    25  UIKit                               0x0035542e UIApplicationMain + 1160
    26  GTMTest                             0x00003500 main + 104
    27  GTMTest                             0x0000273d start + 53
    28  ???                                 0x00000002 0x0 + 2
)
terminate called after throwing an instance of 'NSException'

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

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

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

Ответы [ 2 ]

0 голосов
/ 24 мая 2013

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

0 голосов
/ 03 февраля 2011

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

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