Оставаться OO и Testable при работе с базой данных


16

Каковы некоторые ООП-стратегии для работы с базой данных, но для обеспечения единичного тестирования? Скажем, у меня есть класс User, и моя производственная среда работает против MySQL. Я вижу пару возможных подходов, показанных здесь с использованием PHP:

  1. Передайте $ data_source с интерфейсами для load()и save(), чтобы абстрагировать внутренний источник данных. При тестировании передайте другое хранилище данных.

    $ user = new User ($ mysql_data_source);
    $ user-> load ('bob');
    $ user-> setNickname ('Robby');
    $ User-> Save ();
    
  2. Используйте фабрику, которая обращается к базе данных и передает результирующую строку в конструктор пользователя. При тестировании вручную генерируйте параметр $ row или макетируйте объект в UserFactory :: $ data_source. (Как я могу сохранить изменения в записи?)

    class UserFactory {
        static $data_source;
    
        public static function fetch( $username ) {
            $row = self::$data_source->get( [params] );
    
            $user = new User( $row );
            return $user;
        }
    }
    

У меня рядом есть Шаблоны проектирования и Чистый код , но я изо всех сил пытаюсь найти подходящие концепции.


Ответы:


11

Итак, что вы хотите получить, так это паттерны корпоративной архитектуры приложений Мартина Фаулерса (он также предоставляет каталог на своем веб-сайте здесь ).

В нем он описывает несколько шаблонов для абстрагирования доступа к данным. Первый подход, который вы описываете, - Active Record . Ваш второй подход похож на шлюз таблиц данных .

Еще лучшим подходом является использование O / RM для устранения необходимости написания кода доступа к данным вручную. Я не использовал PHP, так как мы беспокоились о Y2K, но в Википедии есть список вариантов для вас . Я не знаю, насколько они хороши. Однако я могу рассказать вам кое-что, что нужно искать в O / RM:

  • Постоянное невежество : O / RM не должен заставлять ваши бизнес-объекты наследоваться от определенного интерфейса / класса для участия в стратегии доступа к данным.
  • Отображение отношений : вы должны иметь возможность отображать отношения между вашими объектами (у клиента есть заказы, у заказов есть позиции, у позиций есть продукт и т. Д.)
  • Hierachical Mapping : у вас должна быть возможность отображать иерархии классов в базе данных.
  • Поддержка синтаксиса / критериев запроса : вы должны иметь возможность создавать запрос во время выполнения с точки зрения ваших объектов, а не с точки зрения базы данных, а O / RM должен преобразовывать и выполнять запрос к базе данных. Дополнительные точки, если запрос представляет собой строго типизированную цепочку вместо строки.

Есть и другие факторы, которые следует учитывать, но они являются одними из самых важных. Надеюсь это поможет.


6

ИМХО, это зависит от того, что вы хотите протестировать; если вы хотите провести модульное тестирование своей бизнес-логики, вам следует заглушить / насмешливо ( Мартин Фаулер ) доступ к данным, поэтому первое предложение - хорошее начало. Этот вопрос о стековом потоке дает хороший пример C # (я пытался найти несколько примеров PHP, но не смог их найти).

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

Если вы хотите проверить логику хранимых процедур в вашей базе данных, посмотрите на xUnit TestPattern

Надеюсь это поможет


2

Это не обязательно сразу полезный ответ, но если вы действительно обеспокоены тестируемостью базы данных, вы должны посмотреть, как это делается в Ruby on Rails. Насколько я знаю, никто не освещал эту тему лучше или более интуитивно.


2
Ruby on Rails реализует шаблон Active Record по умолчанию.
Можно

0

Я рекомендовал вам проверить решение Symfony Framework для решения подобных проблем. Symfony - это PHP-фреймворк с функциональными тестами.

Вот ссылка , они использовали что-то вроде того, о чем вы думаете.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.