Rhino Mocking и TDD с устаревшим кодом - PullRequest
1 голос
/ 19 августа 2010

Прежде всего позвольте мне сказать, что я работаю с устаревшим кодом. Таким образом, некоторые изменения могут быть сделаны, но не радикальные.

Моя проблема в том, что у меня есть объект «Автомобиль», он довольно простой, но на нем нет интерфейсов или чего-либо еще. Этот проект был создан до того, как TDD действительно начал становиться все более популярным. В любом случае мне нужно добавить новый метод, чтобы изменить начальный пробег автомобиля. Я думал, что это будет хорошим началом, чтобы попробовать TDD и Mocking, поскольку я новичок во всем этом. Моя проблема в том, что мне нужно создать транспортное средство, сделать несколько проверок, которые включают в себя посещение базы данных. Извините, если мой вопрос не ясен на 100%, поэтому я пишу, потому что я немного запутался, когда подходит Rhino Mocks (и если мне это нужно!).

Ответы [ 4 ]

2 голосов
/ 19 августа 2010

Проблема в зависимостях.Ваш класс автомобиля зависит от базы данных.Надеемся, что все взаимодействия с базой данных были инкапсулированы в хороший класс, к которому мы вернемся через секунду.Когда вы запускаете тестовый модуль, вы хотите иметь возможность тестировать класс автомобиля, не заботясь о базе данных.Например, вы хотите проверить, что ваш метод SpeedUp (int x) действительно увеличивает общую скорость на x.В этом методе первое, что он делает, это запрашивает у БД текущую скорость.Это означает, что у вас должна быть БД для тестирования!Дам, это не похоже на очень быстрый тест и не повторяется.Также много настроек для запуска теста.

Разве не было бы здорово, если бы у нас была притворная БД?Вот тут-то и возникает насмешка. Мы создаем макет класса, в котором инкапсулировано все взаимодействие с БД.Затем мы устанавливаем макет, чтобы ответить заранее запрограммированным значением.Так, например, когда мы запрашиваем у БД текущую скорость, вы возвращаете 100.

Итак, теперь, когда мы тестируем, макет возвращает 100, и мы можем утверждать, что SpeedUp (int x) берет 100 и добавляет к нему x.

1 голос
/ 19 августа 2010

Насмешки Rhino могут создавать насмешки только из интерфейсов или абстрактных классов, для которых не существует ваш унаследованный код.

TypeMock может издеваться над чем угодно, но не бесплатно.

Вы можете использовать Microsoft Moles , чтобы их высмеивать.

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

HTH

0 голосов
/ 06 февраля 2014

Не прямой ответ на ваш вопрос.Однако стоит взглянуть на следующее.

Габриэль Шенкер написал о применении TDD в устаревших системах. PTOM - разработка Brownfield - явное указание ваших зависимостей

В этой статье рассказывается о создании dependencies explicit и использовании Dependency Injection.Это также говорит о Poor Man’s Dependency Injection.Это необходимо, когда есть только конструктор по умолчанию.

Что-то вроде

 public OrderService() : this(
    new OrderRepository(),
    new EmailSender(ConfigurationManager.AppSettings["SMTPServer"])
    )

В статье также рассматривается создание оболочки для ConfigurationManager, чтобы сделать ее тестируемой.

0 голосов
/ 19 августа 2010

Легко ли создать экземпляр типа Vehicle (объект), а затем вызвать ваш метод для теста? Если да, то, скорее всего, вам не нужно издеваться.

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

Vehicle  [depends On>] OwnerRepository [satisfied By] SQLOwnerRepository

Итак, вы вводите интерфейс (скажем, OwnerRepository для получения сведений о владельце) для разделения взаимодействия между БД (определения контракта) между ними. Сделайте вашу реальную зависимость (здесь SQLOwnerRepository) реализующей этот интерфейс. Также создайте свой код таким образом, чтобы можно было вводить зависимости, например

public Vehicle (OwnerRepository ownerRepository) 
{  _ownerRepository = ownerRepository;  // cache in member variable }

Теперь в тестовом коде,

Vehicle [depends On >] OwnerRepository [satisifed By] MockOwnerRepository 

У вас есть фреймворки, в которых данный интерфейс мог бы создать имитационную реализацию (см. Фреймворки Rhino / Moq). Таким образом, вам больше не нужно фактическое соединение с БД для проверки класса вашего автомобиля. Моды используются для отвлечения отнимающих много времени / неконтролируемых зависимостей, чтобы ваши тесты выполнялись быстро / предсказуемо.

Я бы порекомендовал прочитать «Внедрение зависимостей», чтобы лучше понять, когда и зачем использовать макеты.

...