2009-09-12 9 views
25

Во время недавнего интервью меня спросили, почему нужно было бы создавать макет объектов. Мой ответ пошел примерно так: «Возьмите базу данных - если вы пишете тестовый код, вы можете не захотеть, чтобы этот тест подключался к рабочей базе данных, где будут выполняться реальные операции».Зачем создавать макетные объекты?

Судя по ответам, мой ответ явно не был тем, что искал интервьюер. Какой лучший ответ?

ответ

30

Я бы резюмировать следующим образом:

  • Изоляция - Вы можете проверить только метод, независимо от того, что он называет. Ваш тест будет испытание на реальное устройство (самое важное ИМХО)
  • Уменьшение времени разработки тестов - это, как правило, быстрее использовать издеваться то, чтобы создать целый класс только для помощи вам испытать
  • Это позволяет вам тест, даже если вы не внедрили все зависимости - вам даже не нужно создавать, например, ваш класс репозитория, и вы сможете протестировать класс, который будет использовать этот репозиторий.
  • Сохраняет вас от внешних ресурсов - помогает в том смысле, что вам не нужно обращаться к базам данных или обращаться к веб-службам, или t о читать файлы, или отправить электронную почту, или зарядить кредитную карту, и так далее ...

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

+14

Конечно, на * плохой стороне Mock Objects происходит тот факт, что при изменении интерфейса реального класса кто-то должен запускать поиск и обновление Mocks, и тем временем все эти «успешные» тесты ложны. –

+6

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

+0

Но это не меняет того факта, что подписчики интерфейса нарушены. – Gutzofter

3

Мощные объекты/функции также могут быть полезны при работе в команде. Если вы работаете над частью базы кода, которая зависит от другой части базы кода, за которую несет ответственность другая, которая еще написана или еще не написана, макет-объект/функция полезны в давая вам ожидаемый результат, чтобы вы могли продолжать работать, не работая, не ожидая, пока другой человек закончит свою работу.

5

При тестировании модулей каждый тест предназначен для тестирования одного объекта. Однако большинство объектов в системе будут иметь другие объекты, с которыми они взаимодействуют. Mock Objects - это фиктивные реализации этих других объектов, используемых для изоляции тестируемого объекта.

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

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

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

Другие виды использования могут заключаться в том, чтобы издеваться над пользовательским интерфейсом при тестировании объекта контроллера в шаблоне MVC. Это позволяет лучше автоматизировать тестирование компонентов пользовательского интерфейса, которые могут несколько имитировать взаимодействие пользователя.

Пример:

public interface IPersonDAO 
{ 
    Person FindById(int id); 
    int Count(); 
} 

public class MockPersonDAO : IPersonDAO 
{ 
    // public so the set of people can be loaded by the unit test 
    public Dictionary<int, Person> _DataStore; 

    public MockPersonDAO() 
    { 
     _DataStore = new Dictionary<int, Person>(); 
    } 

    public Person FindById(int id) 
    { 
     return _DataStore[id]; 
    } 

    public int Count() 
    { 
     return _DataStore.Count; 
    } 
} 
5

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

Рассмотрите подход «сверху вниз»: сначала вы разрабатываете графический интерфейс, но графический интерфейс должен иметь данные. Таким образом, вы создаете базу данных макета, которая возвращает только данные std :: vector <>. Вы определили «контракт» отношений. Кто заботится о том, что происходит внутри объекта базы данных, - пока мой список GUI получает std :: vector <> Я счастлив. Это может помочь предоставить информацию для входа в систему, независимо от того, что нужно для работы графического интерфейса.

Рассмотрите подход снизу вверх. Вы написали парсер, который читает в текстовых файлах с разделителями. Откуда вы знаете, работает ли он? Вы пишете mock 'data-sink' для этого объекта и маршрутизируете данные там, чтобы проверить (хотя обычно), что данные читаются правильно. Для модуля на следующем уровне может потребоваться 2 источника данных, но вы их только написали.

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

Надеется, что это помогает

3

Вот a few situations where mocking is indispensabl е:

  1. При тестировании GUI взаимодействиям
  2. При тестировании Web App
  3. При тестировании кода, который взаимодействует с аппаратное обеспечение
  4. При тестировании устаревших приложений
+0

+1 спасибо за ссылку – k3b

2

Я пойду в другом направлении. Stubbing/Faking делает все, что упоминалось выше, но, возможно, интервьюеры думали о насмехах как обманном объекте, который заставляет тест проходить или терпеть неудачу. Я основываю это на xUnit terminology. Это могло привести к некоторому обсуждению о state testing verses behavior/interaction testing.

Ответ, который они, возможно, искали, - это то, что макет объекта отличается от заглушки. Штук эмулирует зависимость для тестируемого метода. Заглушка не должна приводить к сбою теста. Макет делает это и также проверяет, как и когда он называется. Mocks заставляет тест проходить или терпеть неудачу на основе основного поведения. Это имеет преимущество быть менее зависимым от данных во время теста, но привязывая его более тесно к реализации метода.

Конечно, это предположение, скорее всего, они просто хотели, чтобы вы описали преимущества stubbing и DI.

0

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

IMO - плохой способ заявить пример использования. Вы никогда бы не« подключили его к базе данных prod »во время тестирования с использованием или без mocks. Каждый разработчик должен иметь локальную базу данных разработчика для тестирования. вы бы переместились на базу тестовых сред, а затем, возможно, на UAT и, наконец, на продукт. Вы не издеваетесь над тем, чтобы не использовать живую базу данных, вы издеваетесь над тем, чтобы классы, которые напрямую не зависят от базы данных, не требуют настройки базы данных.

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

Смежные вопросы