Я использую XCTest
и OCMock
для написания модульных тестов для приложения iOS, и мне нужно руководствоваться тем, как наилучшим образом разработать единичный тест, который проверяет, что метод приводит к тому, что метод NSTimer
начал.Запуск модульного теста для проверки запуска NSTimer
Код тестируемой:
- (void)start {
...
self.timer = [NSTimer timerWithTimeInterval:1.0
target:self
selector:@selector(tick:)
userInfo:nil
repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:self.timer forMode:NSDefaultRunLoopMode];
...
}
То, что я хочу, чтобы проверить, что таймер создается с правильными аргументами, и что таймер планируется запустить на цикле выполнения.
Я думал о следующих вариантов, что я не доволен:
- На самом деле ждать таймер стрелять. (Причина мне не нравится: ужасная практика тестирования модулей. Это больше похоже на медленный интеграционный тест.)
- Извлеките стартовый код таймера в частный метод, разоблачите этот частный метод в файле расширения класса на модульные тесты, и использовать макетное ожидание, чтобы проверить, вызван ли частный метод. (Причина мне не нравится: он проверяет, что метод вызван, но не тот метод, который фактически устанавливает таймер для правильной работы. Кроме того, разоблачение частных методов не является хорошей практикой.)
- Предоставить макет
NSTimer
к тестируемому коду. (Причина, по которой мне это не нравится: не удается проверить, что на самом деле он запланирован для запуска, потому что таймеры запускаются через цикл запуска, а не с некоторого метода запускаNSTimer
.) - Предоставьте макет
NSRunLoop
и убедитесь, чтоaddTimer:forMode
: получает называется. (Причина мне не нравится: я должен был бы обеспечить интерфейс в цикле запуска? Это кажется дурацким.)
Может ли кто-нибудь предоставить некоторый юнит-тестирование коучинга?
Вам не нужно проверять, что он _actually получает schedule_ для запуска. Биты планирования и запуска не являются вашим кодом; даже если вы их протестировали, и они не сработали, что вы можете с этим поделать? Вам просто нужно убедиться, что ваш код делает то, что ему нужно сделать до этого момента, правильно взаимодействует с каркасом. Поэтому я думаю, что номер три - это ответ - скажите, что из класса класса «NSTimer» следует ожидать «timerWithTimeInterval: ...» –
Смысл 'NSRunLoop' также имеет смысл; У Майка Эша есть статья, которая, вероятно, будет полезна там: https://www.mikeash.com/pyblog/friday-qa-2010-01-01-nsrunloop-internals.html –
Джош, спасибо за руководство! Я больше думал об этой проблеме, и ваш комментарий к «планированию и запуску битов не является вашим кодом» напомнил мне, что я где-то читал «Не тестируйте реализацию Apple». Это не имело смысла до сих пор. Я пытался разработать свой тест, чтобы охватить все возможные сценарии, но вы просто не можете этого сделать, когда вы используете чей-то код для работы, все, что вы можете сделать, это проверить, что происходит взаимодействие. –