Модульное тестирование - не имеет смысла для меня
Я пытаюсь научиться модульному тестированию и у меня возникает следующая ситуация: я просто не могу разобраться:
- У меня есть модель: SalesOrder - какие модели заказов в интернет-магазине
- SalesOrder имеет свойство под названием gift_message_id
- Идентификатор подарочного сообщения является целочисленным значением и является внешним ключом для модели GiftMessage
- Модель GiftMessage имеет метод, который может взять модель заказа и правильно загрузить экземпляр GiftMessage на основе SalesOrder.
Я пытаюсь написать тест, который точно проверяет это поведение, но в итоге я получаю 2 макета: 1 для SalesOrder и 1 для GiftMessage, и это не имеет смысла. Что я здесь не так делаю?
Метод, который я пытаюсь проверить, выглядит следующим образом:
public function loadGiftMessageByOrderModel(SalesOrder $order)
{
$giftMessageId = $order->getGiftMessageId();
//if the order has a gift message id then load the gift message model and return it
if ($giftMessageId !== false) {
return new GiftMessage($giftMessageId);
}
return false;
}
Как это может быть проверено модулем, учитывая, что данные заказа и подарочного сообщения хранятся в базе данных.
2 ответа
Каждый раз, когда у вас есть метод, который вызывает конструктор, и в конструкторе выполняется нетривиальная работа, у вас возникают проблемы. Наилучший вариант, который я вижу из вышесказанного, состоит в том, чтобы вышеуказанный класс имел GiftMessageFactory
пример. Затем вы можете смоделировать фабрику, чтобы проверить, что она вызывается с соответствующими значениями и соответствующим временем.
Как вы написали loadGiftMessageByOrderModel
функции и объяснил конструктор GiftMessage, я не думаю, что вы можете легко модульное тестирование этого кода. Для того, чтобы провести чистое тестирование, вам нужно загрузить GiftMessage из БД в методе, который не является конструктором. Ваш конструктор не должен вызывать методы, которые взаимодействуют с базой данных. Другой класс или метод должен выполнить эту загрузку, а затем вызвать конструктор. Примерно как то так:
public function loadGiftMessageByOrderModel(SalesOrder $order)
{
$giftMessageId = $order->getGiftMessageId();
//if the order has a gift message id then load the gift message model and return it
if ($giftMessageId !== false) {
// $giftMessageLoader handles loading from the DB; it doesn't create a GiftMessage object
$giftMessageRecord = $giftMessageLoader.loadById( $giftMessageId );
// $giftMessageFactory actually calls the constructor to create a GiftMessage
return $giftMessageFactory.createFromRecord( $giftMessageRecord );
}
return false;
}
Затем вы можете издеваться над $giftMessageLoader.loadById
вызов, чтобы вы контролировали то, что возвращается из базы данных. Вы также сможете проверить, что $giftMessageFactory
вызывает GiftMessage
конструктор соответствующим образом и создает соответствующий объект.
Общий урок здесь заключается в том, что конструкторы должны быть простыми. Они могут проверять параметры, чтобы объект был построен правильно, но, вероятно, они не должны вызывать другие важные части вашего приложения.