Я начинаю новый проект и очень стараюсь использовать TDD для управления дизайном. Я настаивал в течение многих лет и, наконец, получил одобрение, чтобы потратить дополнительное время на этот проект, чтобы использовать его, пока я учусь, как делать это правильно.
Это новый модуль, привязанный к существующей системе. В настоящее время весь доступ к данным осуществляется через веб-сервисы, которые по большей части являются лишь тонкой оболочкой для хранимых процедур базы данных.
Одно требование заключается в том, что для данного магазина я возвращаю все заказы на поставку, которые считаются действительными для этого приложения. Заказ на поставку считается действительным, если его дата отгрузки находится в пределах заданного диапазона от даты открытия магазинов (это для новых магазинов).
Теперь я не могу поместить эту логику в код приложения, так как я не собираюсь возвращать миллион PO, просто чтобы получить дюжину, которую можно применить, к этому хранилищу, учитывая ограничение выше.
Я думал, я мог бы передать диапазон дат в Proc GetValidPO, и он использовал эти значения, чтобы вернуть действительные PO. Но что, если мы добавим еще одно требование к тому, что считается действительным PO?
И как я могу проверить это и убедиться, что он продолжает работать? Мы не используем ORM, и это вряд ли произойдет. И я не могу вызвать БД в моем тесте.
Я застрял.
Моя другая мысль: есть некоторые mocks, которые возвращают действительные данные, другие, которые возвращают некоторые неверные данные, и локальный репозиторий генерирует исключение, если возникают неверные данные, и проверяет, что исключение генерируется, если недействительные данные возвращаются процедурой GetValidPOs (или макет, используемый в тестировании).
Имеет ли это смысл? Или есть лучший способ?
ОБНОВЛЕНИЕ: я могу использовать EF, казалось бы. Теперь мне просто нужно выяснить, как его использовать, и сделать его тестируемым, при этом все еще имея возможность полагаться на хранимые процедуры и сложность разброса данных по нескольким базам данных.
источник
Ответы:
Это серьезный недостаток хранимых процедур в эпоху TDD. У них есть некоторые реальные преимущества, даже сейчас, но по определению любой тест, который выполняет сохраненный процесс, не является модульным тестом; в лучшем случае это интеграционный тест.
Обычное решение, предполагающее, что архитектура не может измениться на использование ORM, состоит в том, чтобы не помещать эти тесты в комплект модульных тестов; вместо этого поместите тесты в комплект интеграции. Вы по-прежнему можете запускать тест всякий раз, когда хотите убедиться, что он работает, но поскольку затраты на настройку теста (инициализация БД с надлежащими данными теста) высоки, и это затрагивает ресурсы, которые может выполнить агент модульного теста вашего сборщика. иметь доступ к, это не должно быть в наборе модульных тестов.
Вы по-прежнему можете выполнять код модульного тестирования, который требует данных, абстрагируя все, что нельзя выполнить модульным тестом (классы ADO.NET), в класс DAO, который затем можно смоделировать. Затем вы можете проверить, что ожидаемые вызовы сделаны, используя код, и воспроизвести реальное поведение (например, не найдя результатов), что позволяет тестировать различные варианты использования. Тем не менее, фактическая настройка SqlCommand для вызова хранимого процесса в значительной степени является последним, что вы можете выполнить модульным тестом, отделив создание команды от выполнения команды и издеваясь над исполнителем команды. Если это звучит как разделение интересов, это может быть; помните: «нет проблемы, которая не может быть решена другим слоем косвенности, за исключением слишком большого количества слоев косвенности». В какой-то момент вы должны сказать «достаточно; я просто не могу провести юнит-тестирование, мы
Другие опции:
Протестируйте сохраненный процесс, используя «недолговечный» экземпляр СУБД, такой как SQLite. Обычно это проще сделать при использовании ORM, но затем тест можно выполнить «в памяти» (или с предварительно установленным файлом базы данных, включенным в набор тестов). Все еще не является модульным тестом, но его можно запускать с высокой степенью изоляции (СУБД является частью запущенного процесса, а не того, к чему вы подключаетесь удаленно, что может быть в центре чьего-либо конфликтующего набора тестов). Недостатком является то, что изменения в хранимых процессах могут происходить в производственном процессе без тестирования, отражающего эти изменения, поэтому вам нужно быть дисциплинированным, чтобы убедиться, что изменения вначале были внесены в тестовую среду.
Рассмотрите возможность обновления до ORM. ORM с провайдером Linq (практически у всех таковых есть) позволит вам определить запрос как оператор Linq; этот оператор затем может быть передан в фиктивный репозиторий, в котором имеется коллекция тестовых данных в памяти для его применения. Таким образом, вы можете проверить правильность запроса, даже не касаясь БД (вам все равно следует выполнить запрос в среде интеграции, чтобы проверить, что поставщик Linq может правильно обработать запрос).
источник
Мой совет - разделяй и властвуй . Забудьте на время о базе данных и постоянстве и сконцентрируйтесь на тестировании поддельных реализаций ваших репозиториев или объектов доступа к данным.
Я бы издевался над хранилищем, которое возвращает заказы на покупку. Создайте макет с двадцатью нечетными заказами на покупку.
Заглушите вызов GetValidPO, чтобы он вызывал вашу ложную реакцию, а не процедуру базы данных.
Вам необходим юнит-тест, чтобы убедиться, что верные данные возвращаются из макета.
Вам также необходим интеграционный тест, чтобы убедиться, что правильные данные возвращаются из базы данных. Интеграционный тест потребует некоторой настройки и очистки. Например, перед запуском интеграционного теста запустите базу данных, запустив скрипт. Убедитесь, что ваш скрипт работает. Запросите базу данных, вызвав ваши хранимые процедуры. Убедитесь, что ваши результаты верны. Очистить базу данных.
Как я уже сказал, вам нужен макет, который возвращает хотя бы некоторые данные, которые вы можете запросить.
Когда вы запрашиваете данные, вы хотите убедиться, что ваша система может корректно обрабатывать исключения. Поэтому вы издеваетесь над поведением, чтобы оно вызывало исключения в определенных сценариях. Затем вы пишете тесты, чтобы убедиться, что ваша система может корректно обрабатывать эти исключения.
источник
Точно так же, как модульное тестирование Java или Javascript означает написание модульных тестов с использованием языка Java для java, так и модульное тестирование функций Javascript с помощью Javascript, написание автоматизированных тестов, побуждающих вас писать хранимые процедуры, означает, что искомая библиотека модульных тестов основана на сохраненных процедуры.
Иными словами, используйте хранимые процедуры для тестирования хранимых процедур, потому что:
Точно так же, как TDD в OO-языке, вы хотите, чтобы ваш модульный тест настраивал только строку или около того данных для проверки того, что нужно для процедуры (минимализм, есть только то, что нужно вашим простым тестам). В результате у вас будет несколько простых модульных тестов для каждой хранимой процедуры. Эти простые тесты будет проще поддерживать, чем сложные тесты, которые зависят от большого набора данных, который не может легко отобразить то, что на самом деле нужно тесту.
источник