Одним из примеров случая сбоя, который вы хотите предварительно отловить, является то, что тестируемый объект использует слой кэширования, но не может сохранить данные по мере необходимости. Затем, если вы запросите объект, он скажет: «Да, у меня есть новое имя и адрес», но вы хотите, чтобы тест не прошел, потому что он на самом деле не сделал то, что должен был.
В качестве альтернативы (и пропуская нарушение единственной ответственности), предположим, что требуется сохранить версию строки в кодировке UTF-8 в байтово-ориентированном поле, но на самом деле сохраняется Shift JIS. Какой-то другой компонент собирается прочитать базу данных и ожидает увидеть UTF-8, отсюда и требование. Затем в оба конца этот объект сообщит правильное имя и адрес, потому что он преобразует его обратно из Shift JIS, но ошибка не обнаружена вашим тестом. Надеемся, что это будет обнаружено в более позднем интеграционном тесте, но весь смысл модульных тестов состоит в том, чтобы выявлять проблемы на ранних этапах и точно знать, какой компонент отвечает.
Если один из них не делает то, что должен, его собственный тестовый случай не пройден, и мы можем исправить это и снова запустить тестовую батарею.
Вы не можете этого допустить, потому что если вы не будете осторожны, вы напишите взаимозависимый набор тестов. "Это экономит?" test вызывает метод save, который тестирует, а затем метод load, чтобы подтвердить сохранение. "Это загружается?" test вызывает метод save для настройки тестового прибора, а затем метод загрузки, который он тестирует, чтобы проверить результат. Оба теста основаны на правильности метода, который они не тестируют, что означает, что ни один из них на самом деле не проверяет правильность метода, который он тестирует.
Подсказка, что здесь есть проблема, состоит в том, что два теста, которые предположительно тестируют разные модули, на самом деле делают одно и то же . Они оба вызывают установщик, за которым следует получатель, а затем проверяют, является ли результат исходным значением. Но вы хотели проверить, что установщик сохраняет данные, а не то, что пара установщик / получатель работает вместе. Итак, вы знаете, что что-то не так, вам просто нужно выяснить, что и исправить тесты.
Если ваш код хорошо спроектирован для модульного тестирования, то есть как минимум два способа проверить, действительно ли данные были правильно сохранены тестируемым методом:
смоделируйте интерфейс базы данных, и сделайте, чтобы ваша ложная запись запомнила тот факт, что для него были вызваны надлежащие функции с ожидаемыми значениями. Этот тест проверяет, что метод делает то, что должен, и является классическим модульным тестом.
передать ему фактическую базу данных с точно таким же намерением , чтобы записать, правильно ли были сохранены данные. Но вместо того, чтобы иметь поддельную функцию, которая просто говорит: «Да, я получил правильные данные», ваш тест считывает данные из базы данных напрямую и подтверждает, что это правильно. Возможно, это не самый чистый тест, потому что весь движок базы данных довольно полезен для написания прославленного макета, и у меня больше шансов пропустить какую-то тонкость, которая делает тест пройденным, даже если что-то не так (например, я не должен использовать то же соединение с базой данных для чтения, которое использовалось для записи, потому что я могу увидеть незафиксированную транзакцию). Но это проверяет правильность, и, по крайней мере, вы знаете, что это точно реализует весь интерфейс базы данных без необходимости писать какой-либо фиктивный код!
Так что это просто деталь реализации теста, считываю ли я данные из тестовой базы данных JDBC или я имитирую базу данных. В любом случае дело в том, что я могу лучше протестировать модуль, изолировав его, чем смогу, если позволю ему сговориться с другими неправильными методами в том же классе, чтобы они выглядели правильно, даже если что-то не так. Поэтому я хочу использовать любые удобные средства для проверки правильности сохраненных данных, за исключением доверия к компоненту, метод которого я тестирую.
Если ваш код плохо спроектирован для модульного тестирования, у вас может не быть выбора, потому что объект, метод которого вы хотите протестировать, может не принять базу данных как внедренную зависимость. В этом случае дискуссия о том, как лучше изолировать тестируемый блок, переходит в дискуссию о том, насколько близко можно добраться до изоляции тестируемого блока. Вывод тот же, хотя. Если вы можете избежать заговоров среди неисправных модулей, тогда вы делаете это, при условии наличия свободного времени и всего, что, по вашему мнению, будет более эффективным для обнаружения ошибок в коде.