Я думаю, что этот вопрос является довольно хорошим примером сложностей, связанных с модульным тестированием, интеграционным тестированием, а также границ между ними и полезностью каждого из них.
Пока нет «правильного» ответа, вот что я бы сделал. Надеемся, что это даст некоторое представление и поможет вам выяснить, что лучше всего соответствует вашим потребностям.
Оставлять его в базе данных для обнаружения дубликатов очень разумно - базы данных хороши в этом, и это уменьшает объем кода, который вам придется писать. Достаточно простого уникального ограничения (product-name, project). И действительно, попытка применить это в любом месте, кроме ограничения базы данных (например, выполнить чтение, а затем проверить логику приложения перед записью), может привести к гоночным условиям, если вы не очень осторожны в отношении границ транзакций. Итак, учитывая, что использование базы данных для обеспечения соблюдения этого ограничения является наилучшим подходом, как мы можем его протестировать?
Юнит-тесты: Я думаю, что юнит-тест - отличный вариант, если это вообще возможно. Модульные тесты всегда должны быть первым выбором, основанным на тестовой пирамиде . Однако вашему модульному тесту не нужно проверять способность базы данных применять уникальное ограничение (это выходит за рамки «тестируемого модуля»). Вместо этого ваш модульный тест должен утверждать, что ваша система ведет себя правильно, если база данных выдает исключение из-за уникального нарушения ограничения. Нужно ли переводить это исключение в пользовательское исключение на любом уровне вашего приложения? Если это так, то юнит тест это. Нужно ли вашему приложению возвращать определенный код состояния HTTP из-за исходного или переведенного исключения? Если это так, проверьте это модулем.
Интеграционные тесты: Поскольку вы используете базу данных для обеспечения соблюдения уникального ограничения, нет способа полностью проверить, что взаимодействие между вашей системой и базой данных будет функционировать, как ожидается, без интеграционного теста. Есть несколько вариантов, которые вы можете использовать здесь, и вам придется решить, какой из них лучше всего подходит для вашего случая использования. В некоторых приложениях Java довольно распространенной практикой является загрузка вашей схемы в базу данных H2 в памяти и выполнение минимального интеграционного теста между вашим классом доступа к базе данных и только что настроенной тестовой базой данных. Другие могли бы предпочесть более комплексный подход к интеграционному тестированию, который включал бы запуск вашего приложения на реальной базе данных, а затем запуск тестов API для этого.
Вы упомянули, что у вас есть много случаев, похожих на этот, поэтому подумайте, какой подход будет лучше масштабироваться, чтобы протестировать все сценарии, которые вы хотите. Недостатком сквозных тестов является то, что их может быть медленнее запускать и труднее управлять из-за их дополнительных зависимостей, что может потенциально продлить цикл обратной связи. С другой стороны, они предоставляют возможность утверждать в условиях, которые немного ближе к производственной среде.