Вот общий подход, который я пытаюсь использовать. Я имею в виду тесты примерно на трех или четырех уровнях: юнит-тесты, тесты взаимодействия, интеграционные тесты, приемочные тесты.
На уровне модульного теста это просто код. Любое взаимодействие с базой данных отключается либо вручную, либо с использованием одной из популярных платформ, поэтому загрузка данных не является проблемой. Они бегут быстро и следят за тем, чтобы объекты работали как положено. Это учитывает очень быстрые циклы записи-тестирования / записи кода / запуска теста. Поддельные объекты обслуживают данные, необходимые для каждого теста.
Тесты взаимодействия проверяют взаимодействия нетривиальных взаимодействий классов. Опять же, база данных не требуется, она отключена.
Теперь на уровне интеграции я тестирую интеграцию компонентов, и вот тут-то добавляются реальные базы данных, очереди, сервисы, yada yada. Если я могу, я буду использовать одну из популярных баз данных в памяти , так что инициализация не является проблемой. Он всегда начинается пустым, и я использую служебные классы для очистки базы данных и загрузки именно тех данных, которые мне нужны, перед каждым тестом, чтобы между тестами не было никакой связи.
Проблема, с которой я столкнулся при использовании баз данных в памяти, заключается в том, что они часто не поддерживают все необходимые мне функции. Например, возможно, мне требуется внешнее соединение, а БД в памяти этого не поддерживает. В этом случае я, как правило, проверяю локальную обычную базу данных, такую как MySQL, и снова очищаю ее перед каждым тестом. Поскольку приложение развернуто в рабочей среде в отдельной среде, эти данные не затрагиваются циклом тестирования.