Стратегии использования фиктивных объектов при модульном тестировании DAO - PullRequest
2 голосов
/ 28 декабря 2008

Мне любопытно, какие стратегии люди нашли для модульного тестирования класса доступа к данным, который не включает загрузку (и, вероятно, выгрузку) реальной базы данных для каждого метода тестирования? Используете ли вы фиктивные объекты для представления соединения с базой данных? Если да, то требуется ли передавать фиктивный объект в каждый тестируемый метод и, таким образом, заставлять API требовать реального соединения с БД в качестве параметра для каждого метода? Или вы передаете фиктивный объект в конструктор при setup ()?

У меня есть класс, который реализует шаблон Data Mapper (или, может быть, шлюз). Это класс, отвечающий за инкапсуляцию SQL и возврат (или сохранение) «бизнес-объектов». Остальная часть кода может взаимодействовать с этим уровнем отображения и бизнес-объектами, полностью игнорируя модель постоянства. Этот код должен иметь / поддерживать или просто знать о действующем соединении БД в реальной системе. Подражать этому тесту сложно.

Проблема в том, как выполнить модульное тестирование одного из этих классов картографа. Практика создания модульного теста в xUnit, которую я видел чаще всего, заключается в использовании метода теста setup () для создания экземпляра SUT (тестируемой системы), обычно вашего тестируемого объекта, и сохранения его в локальной системе. переменная в тестовом классе. Затем каждый из ваших методов тестирования взаимодействует с уникальным экземпляром этого SUT.

Предполагается, что все, что вы делаете в методе setup (), предположительно будет реплицировано где-то в вашем реальном коде. Таким образом, вы должны думать о процессе установки как «это то, что я захочу многократно воспроизводить каждый раз, когда мне нужно использовать этот объект в реальном мире». Если я передаю соединение db в конструктор mapper в настройке, это нормально, но разве это не значит, что мне придется передавать живое соединение db в конструктор объекта mapper каждый раз, когда я действительно хочу его использовать? Представьте, что у вас есть все виды мест, где вам нужно получить или сохранить бизнес-объект, и что для использования объекта отображения данных вам необходимо каждый раз передавать соединение db?

В моем случае я пытаюсь установить тесты для этих объектов отображения данных, которые достигают следующего:

  1. Не требуется, чтобы объект подключения к базе данных создавался и передавался в каждый метод класса mapper.
  2. Не требуется, чтобы контрольный пример либо подключался к реальной базе данных, либо создавал действительную, но "тестовую" базу данных на лету для каждого метода тестирования.

В основном я видел два предложения: передать объект соединения в качестве параметра (о котором я уже говорил) или расширить класс SUT только для теста и переопределить любой процесс установки соединения БД, который у вас есть в реальном мире, для использования макета система вместо.

Мне любопытно, сталкивался ли кто-нибудь еще с этими проблемами на каком-либо языке, и что вы сделали для их решения? Может быть, есть что-то очевидное, чего мне не хватает?

Ответы [ 4 ]

3 голосов
/ 28 декабря 2008

По моему опыту, ответственность за подключение к базе данных является больным пунктом в доступе к данным. Я решил это, позволив DAO позаботиться об этом на основе файла конфигурации (app.config и т. Д.). Таким образом, мне не нужно беспокоиться об этом, когда я пишу свои тесты. DAL сохраняет один или несколько профилей подключения к базе данных и подключается / отключается при каждом доступе к данным, поскольку в конечном итоге пул подключений позаботится о физическом подключении / отключении.

Еще одна вещь, которая помогла мне, - использовать dbUnit для загрузки базовых данных перед запуском тестов. Я обнаружил, что проще перейти прямо к базе данных, чем использовать фиктивные объекты. Кроме того, подключаясь к реальной базе данных, я могу (до определенного момента) проверить параллелизм, выдавая команды в разных потоках - фиктивные объекты не дадут мне реального поведения.

0 голосов
/ 26 октября 2012

В зависимости от того, насколько сложна настройка вашей базы данных, это может быть отличным вариантом, используя хранилище в памяти.

Обычно я выполняю свое модульное тестирование в сеансе SQLite в памяти. Это полная база данных 100% в памяти, без файлов, без необходимости конфигурации. Всего одна строка.

Теперь это не всегда вариант. SQLite не поддерживает все возможности sql полноценных серверных баз данных. Обычно я использую слой, пытаясь сделать мою базу данных кода независимой. В этих случаях я просто переключаюсь на экземпляр базы данных в памяти, который быстро создаю / уничтожаю в памяти во время каждого setUp / tearDown.

Вы используете какой-либо средний слой для доступа к вашей базе данных? В большинстве случаев наибольшим преимуществом использования такого типа промежуточного программного обеспечения является не переносимость базы данных, а упрощенное использование тестов.

0 голосов
/ 02 января 2009

Это зависит от того, что вы действительно пытаетесь проверить. Если вы хотите проверить, что ваш SQL выполняет то, что вы ожидаете, то это действительно Integration Test территория. Предполагая, что вы используете Java, вы можете использовать для этого несколько решений RDBMS на чистой Java (Apache Derby, HSQLDB, H2).

Если, с другой стороны, вы на самом деле просто тестируете свой Java <-> код JDBC (т. Е. Читаете из ResultSets), то вы можете макетировать практически все соответствующие части JDBC, поскольку в основном интерфейсы. JMock отлично подходит для этого. Просто добавьте метод setConnection() в тестируемый класс и передайте имитированный java.sql.Connection, который будет выполнять ваши ставки. Это очень хорошо работает для того, чтобы тесты были короткими и приятными.

0 голосов
/ 28 декабря 2008

Вы можете использовать DbUnit для тестирования SQL

...