Я начинаю считать, что модульное тестирование высокого уровня, хорошо написанного кода, требующего широкого использования макетных объектов, практически не имеет ценности. Мне интересно, правильно ли это утверждение, или я чего-то не хватает?
Что я подразумеваю под высоким уровнем? Это классы и функции, расположенные вблизи верхней части пищевой цепи. Их вход и выход имеют тенденцию быть пользователем и пользовательским интерфейсом. Большая часть их работы состоит в том, чтобы вводить пользовательский ввод и делать серию вызовов для лиц нижнего уровня. У них часто мало или вообще нет значимых возвращаемых значений.
Что я имею в виду, хорошо написав? В этом случае я имею в виду код, который отделен от его зависимостей (с использованием интерфейсов и инъекции зависимостей), а строка за строкой находится на согласованном уровне абстракции. Нет никаких сложных алгоритмов и нескольких условностей.
Я ненавижу, записывая единичные тесты для этого типа кода. Единичные тесты состоят почти полностью из макетной установки объекта. Строка за строкой unit test читается почти как зеркальный образ реализации. Фактически, я пишу модульные тесты, глядя на реализацию. "Сначала я утверждаю, что этот макет-метод вызывается, тогда я утверждаю, что этот макет-метод называется..." и т.д. Я должен тестировать поведение метода, а не то, что он вызывает правильную последовательность методов. Другое дело: я обнаружил, что эти тесты чрезвычайно хрупки для рефакторинга. Если тест настолько хрупкий, что он полностью разрушается и должен быть переписан, когда тестируемый код подвергается рефакторингу, то не потеряно ли одно из основных преимуществ модульного тестирования?
Я не хочу, чтобы это сообщение было помечено как аргументированное, или не вопрос. Поэтому я прямо изложу свой вопрос: что является правильным способом для unit test типа кода, который я описал, или он понимает, что не все нуждается в unit test?