Подтвердить что ты не робот

Зачем создавать макетные объекты?

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

При тестировании модулей каждый тест предназначен для тестирования одного объекта. Однако большинство объектов в системе будут иметь другие объекты, с которыми они взаимодействуют. 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;
    }
}

Ответ 3

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

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

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

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

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

Ответ 4

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

Ответ 6

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

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

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

Ответ 7

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

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

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