2011-01-14 4 views
1

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

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: не вызывается.

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

ответ

0

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

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

Не имеет значения, к сожалению. –

-1

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

Смежные вопросы