Я работаю над проектом, в котором внутренние вызовы класса обычны, но в результате получаются простые значения. Пример ( не реальный код ):
public boolean findError(Set<Thing1> set1, Set<Thing2> set2) {
if (!checkFirstCondition(set1, set2)) {
return false;
}
if (!checkSecondCondition(set1, set2)) {
return false;
}
return true;
}
Написание модульных тестов для этого типа кода действительно сложно, так как я просто хочу протестировать систему условий, а не реализацию реальных условий. (Я делаю это в отдельных тестах.) На самом деле было бы лучше, если бы я передавал функции, которые реализуют условия, а в тестах я просто предоставляю имитацию. Проблема с этим подходом - шумность: мы часто используем дженерики .
Рабочий раствор; однако сделать тестируемый объект шпионом и смоделировать вызовы внутренних функций.
systemUnderTest = Mockito.spy(systemUnderTest);
doReturn(true).when(systemUnderTest).checkFirstCondition(....);
Проблема здесь заключается в том, что реализация SUT эффективно изменяется, и может быть проблематично синхронизировать тесты с реализацией. Это правда? Есть ли лучшая практика, чтобы избежать этого хаоса внутренних вызовов методов?
Обратите внимание, что речь идет о частях алгоритма, поэтому разбиение его на несколько классов может оказаться нежелательным решением.
источник
Если и то,
findError()
и другоеcheckFirstCondition()
являются открытыми методами вашего класса, тоfindError()
это фактически фасад для функциональности, которая уже доступна из того же API. В этом нет ничего плохого, но это означает, что вы должны написать для него тесты, которые очень похожи на уже существующие тесты. Это дублирование просто отражает дублирование в вашем общедоступном интерфейсе. Это не повод рассматривать этот метод иначе, чем другие.источник
Модульные тесты должны проверить контракт; это единственная важная вещь для них. Тестирование всего, что не является частью контракта, является не только пустой тратой времени, но и потенциальным источником ошибок. Каждый раз, когда вы видите, как разработчик меняет тесты, когда он меняет детали реализации, должны прозвучать сигналы тревоги; этот разработчик может (умышленно или нет) скрывать свои ошибки. Умышленное тестирование деталей реализации порождает эту дурную привычку, повышая вероятность того, что ошибки будут маскироваться.
Внутренние вызовы являются деталями реализации и должны представлять интерес только для измерения производительности . Который обычно не работа модульных тестов.
источник
a
содержит вызов методаb
в том же классе, то тестыa
должны включать тестыb
. И нет никакого способа изменить это, покаb
это не передается вa
качестве параметра. Но другого решения, я вижу, нет.b
является частью общедоступного интерфейса, он все равно должен быть протестирован. Если это не так, его не нужно проверять. Если вы сделали это публично только потому, что хотели его протестировать, вы сделали неправильно.Во-первых, мне интересно, что сложно проверить в примере функции, которую вы написали? Насколько я вижу, вы можете просто передать различные входные данные и проверить, чтобы убедиться, что возвращается правильное логическое значение. Что мне не хватает?
Что касается шпионов, то так называемое тестирование «белого ящика», в котором используются шпионы и имитаторы, - это на порядки больше работы для написания, не только потому, что написано гораздо больше тестового кода, но каждый раз, когда реализация изменено, вы также должны изменить тесты (даже если интерфейс остается прежним). И этот вид тестирования также менее надежен, чем тестирование черного ящика, потому что вам нужно убедиться, что весь этот дополнительный тестовый код корректен, и в то же время вы можете верить, что блочные тесты черного ящика не пройдут, если они не соответствуют интерфейсу. Вы не можете доверять этому из-за чрезмерного использования макетов, потому что иногда тест даже не тестирует много реального кода, а только макеты. Если макеты неверны, скорее всего, ваши тесты пройдут успешно, но ваш код все еще не работает.
Любой, кто имеет опыт в тестировании белого ящика, может сказать вам, что ему сложно писать и поддерживать. В сочетании с тем фактом, что они менее надежны, тестирование «белого ящика» в большинстве случаев значительно уступает.
источник