Книга: Экстремальное программирование. Разработка через тестирование
Поддельный объект (Mock Object)
Поддельный объект (Mock Object)
Как выполнять тестирование объекта, который базируется на сложном и тяжеловесном ресурсе? Создайте поддельную версию ресурса, которая будет возвращать константы.
Использование поддельных объектов – это тема для отдельной книги. Существует огромное количество материала, посвященного поддельным объектам[16]. Здесь я попытаюсь очень коротко познакомить читателей с этой концепцией.
Классическим примером является база данных. Чтобы запустить базу данных, требуется значительное время, поддержка чистоты базы данных требует дополнительных затрат, кроме того, если база данных располагается на удаленном сервере, ваши тесты будут связаны с конкретным физическим местоположением в сети. Наконец, база данных является емким источником ошибок разработки.
Чтобы уменьшить количество проблем, рекомендуется в процессе тестирования отказаться от работы непосредственно с базой данных. Большинство тестов пишется в отношении объекта, который функционирует подобно базе данных, однако располагается в оперативной памяти.
public void testOrderLookup() {
Database db = new MockDatabase();
db.expectQuery("select order_no from Order where cust_no is 123");
db.returnResult(new String[] {"Order 2","Order 3"});
.
}
Если объект MockDatabase не принимает ожидаемого запроса, он генерирует исключение. Если запрос корректен, объект возвращает нечто, напоминающее результирующий набор данных, состоящий из нескольких постоянных строк.
Помимо высокой производительности и надежности поддельные объекты обладают еще одним преимуществом: читабельностью. Если вы работаете с реальной базой данных, заполненной реальными данными, в результате обработки запроса вы можете получить ответ, состоящий из 14 строк. Возможно, вам будет нелегко понять, откуда взялось число 14 и в чем, собственно, состоит смысл теста.
Если вы хотите воспользоваться поддельными объектами, не следует хранить тяжеловесные ресурсы в глобальных переменных (даже если они замаскированы с использованием шаблона «Одиночка» (Singleton)). Если вы так поступите, вам придется вначале настроить глобальный поддельный объект, затем выполнить тест, а затем позаботиться о том, чтобы вернуть поддельный объект в исходное состояние.
В свое время я очень строго следил за выполнением этого правила. Мы вместе с Массимо Арнольди (Massimo Arnoldi) разрабатывали код, который взаимодействовал с набором курсов обмена валют, хранящимся в глобальной переменной. Для разных тестов требовалось использовать разные наборы данных, и в некоторых случаях курсы обмена валют должны были быть разными для разных тестов. Вначале мы пытались использовать для тестирования глобальную переменную, однако в конце концов нас это утомило, и однажды утром (смелые решения, как правило, приходят ко мне по утрам) мы решили передавать объект Exchange (в котором хранились курсы обмена) в качестве параметра везде, где это было необходимо. Мы думали, что нам придется модифицировать сотни методов. Однако дело кончилось тем, что мы добавили дополнительный параметр в десять или пятнадцать методов и по ходу дела подчистили другие аспекты дизайна.
Шаблон поддельных объектов заставляет тщательно следить за видимостью объектов, снижая взаимозависимости между ними. Поддельные объекты добавляют в проект некоторый риск, – что, если поддельный объект ведет себя не так, как реальный объект? Чтобы снизить этот риск, вы можете разработать специальный набор тестов для поддельных объектов, которые должны быть выполнены в отношении реального объекта, чтобы убедиться в том, что имитация достаточно близка к оригиналу.
- 1.1. Введение в объектно-ориентированное программирование
- ЧАСТЬ IV. База данных и ее объекты.
- 1.1.1. Что такое объект
- Практическая работа 53. Запуск Access. Работа с объектами базы данных
- Физические объекты
- Иерархия объектов в InterBase
- Имена объектов длиной 68 символов
- Создание объектов Collection
- 7.12. Объективизация времени
- 3.3. Определение объектов защиты
- 5.2.3. Действия с объектами Numbers
- Объекты без прототипов