Как новичок в практике разработки, основанной на тестировании, я часто попадаю в затруднительное положение относительно того, как выполнить модульное тестирование устойчивости к базе данных.
Я знаю, что технически это будет интеграционный тест (а не модульный тест), но я хочу найти лучшие стратегии для следующего:
Каковы лучшие практики для этого?
Что касается тестирования SQL: я знаю, что это можно сделать, но если я использую O / R Mapper, например NHibernate, он добавляет некоторые бородавки именования в псевдонимах, используемых для выходных запросов, и, поскольку это несколько непредсказуемо, я не уверен Я могу проверить это.
Должен ли я просто отказаться от всего и просто доверять NHibernate? Я не уверен, что это разумно.





Вы выполняете модульное тестирование, имитируя соединение с базой данных. Таким образом, вы можете создавать сценарии, в которых определенные запросы в потоке вызова метода завершаются успешно или терпят неудачу. Я обычно строю свои фиктивные ожидания таким образом, что фактический текст запроса игнорируется, потому что я действительно хочу проверить отказоустойчивость метода и то, как он себя обрабатывает - специфика SQL не имеет отношения к этой цели.
Очевидно, это означает, что ваш тест на самом деле не будет проверять, что метод работает, потому что SQL может быть неправильным. Вот здесь и вступают в силу интеграционные тесты. Я ожидаю, что кто-то другой даст более подробный ответ, так как я только начинаю разбираться с ними сам.
Я бы также поиздевался над базой данных и убедился, что запросы соответствуют вашим ожиданиям. Есть риск, что тест проверит неправильный sql, но это будет обнаружено в интеграционных тестах.
Проблема, с которой я столкнулся при постоянном модульном тестировании, особенно без ORM и, таким образом, имитируя вашу базу данных (соединение), заключается в том, что вы действительно не знаете, успешны ли ваши запросы. Возможно, ваши запросы специально разработаны для конкретной версии базы данных и успешно выполняются только с этой версией. Вы никогда этого не узнаете, если будете издеваться над своей базой данных. Так что, на мой взгляд, постоянство модульного тестирования имеет ограниченное применение. Вы всегда должны добавлять тесты, запускаемые для целевой базы данных.
Что касается NHibernate, я бы определенно рекомендовал просто издеваться над NHibernate API для модульных тестов - доверяйте библиотеке, чтобы она поступала правильно. Если вы хотите убедиться, что данные действительно поступают в БД, выполните интеграционный тест.
Технически юнит-тесты устойчивости не являются юнит-тестами. Это интеграционные тесты.
С C#, использующим mbUnit, вы просто используете атрибуты SqlRestoreInfo и RollBack:
[TestFixture]
[SqlRestoreInfo(<connectionsting>, <name>,<backupLocation>]
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
[RollBack]
public void TEST()
{
//test insert.
}
}
То же самое можно сделать и в NUnit, за исключением того, что названия атрибутов немного отличаются.
Что касается проверки, если ваш запрос успешен, вам обычно нужно выполнить второй запрос, чтобы увидеть, была ли база данных изменена так, как вы ожидали.
Загляните в блок БД. Это библиотека Java, но должен быть эквивалент C#. Это позволяет вам подготовить базу данных с набором данных, чтобы вы знали, что находится в базе данных, а затем вы можете взаимодействовать с DB Unit, чтобы увидеть, что находится в базе данных. Он может работать со многими системами баз данных, поэтому вы можете использовать свою фактическую настройку базы данных или использовать что-то еще, например HSQL в Java (реализация базы данных Java с опцией в памяти).
Если вы хотите проверить, что ваш код правильно использует базу данных (что вам, скорее всего, следует делать), то это способ изолировать каждый тест и убедиться, что база данных подготовила ожидаемые данные.
Я написал здесь сообщение о модульное тестирование уровня данных, которое касается именно этой проблемы. Приносим извинения за (постыдный) плагин, но статья слишком длинная, чтобы размещать ее здесь.
Надеюсь, это поможет вам - за последние 6 месяцев он очень хорошо сработал для меня в трех активных проектах.
С уважением,
Роб Джи
Как и Майк Стоун сказал, DbUnit отлично подходит для приведения базы данных в известное состояние перед запуском ваших тестов. Когда ваши тесты будут завершены, DbUnit может вернуть базу данных в состояние, в котором она была до запуска тестов.
Обычно я создаю репозиторий, использую его, чтобы сохранить свою сущность и получить новую. Затем я утверждаю, что извлеченное равно сохраненному.
Для проектов на основе JDBC можно использовать мой фреймворк Acolyte: http://acolyte.eu.org. Он позволяет смоделировать доступ к данным, которые вы хотите протестировать, используя абстракцию JDBC, без необходимости управлять конкретной тестовой БД.
Я согласен, хотя я никогда не был сторонником TDD, я определенно вижу много преимуществ TDD, но чтобы игнорировать реальность и не проверять по-настоящему свои записи, входящие и исходящие из вашей базы данных, вы понятия не имеете, что на самом деле будет делать ваше приложение. в дикой природе. Так много раз, прежде чем мне приписывали "ошибку", что мой код не работал, я запускал свои модульные тесты и обнаруживал, что другой разработчик топтал весь мой sproc (злые злые sprocs) и никогда не заботился о запуске мои модульные тесты, чтобы увидеть, как они взорвали всю систему.