Я новичок в модульном тестировании, и я постоянно слышу слова «фиктивные объекты». С точки зрения непрофессионала, может ли кто-нибудь объяснить, что такое фиктивные объекты и для чего они обычно используются при написании модульных тестов?
unit-testing
mocking
agentbanks217
источник
источник
Ответы:
Поскольку вы говорите, что вы новичок в модульном тестировании, и попросили фиктивные объекты в «терминах непрофессионала», я попробую пример неспециалистов.
Модульное тестирование
Представьте себе модульное тестирование для этой системы:
Как правило, легко представить тестирование низкоуровневого компонента, такого как
cook
:Тест-водитель просто заказывает разные блюда и проверяет, что повар возвращает правильное блюдо для каждого заказа.
Труднее протестировать средний компонент, такой как официант, который использует поведение других компонентов. Наивный тестировщик может протестировать компонент официанта так же, как мы тестировали компонент готовки:
Тест-водитель заказывает разные блюда и гарантирует, что официант вернет правильное блюдо. К сожалению, это означает, что этот тест компонента официанта может зависеть от правильного поведения компонента приготовления. Эта зависимость еще хуже, если у компонента кулинарии есть какие-то недружелюбные к тесту характеристики, такие как недетерминированное поведение (меню включает сюрприз шеф-повара как блюдо), множество зависимостей (повар не готовит без всего своего персонала) или много ресурсы (некоторые блюда требуют дорогих ингредиентов или час, чтобы приготовить).
Поскольку это тест официанта, в идеале мы хотим проверить только официанта, а не повара. В частности, мы хотим убедиться, что официант правильно передает заказ клиента повару и правильно доставляет еду повара клиенту.
Модульное тестирование означает независимое тестирование модулей, поэтому лучшим подходом было бы изолировать тестируемый компонент (официант), используя то, что Фаулер называет тестовыми двойниками (манекены, заглушки, подделки, макеты) .
Здесь, тестовый повар "в сговоре" с тестовым водителем. В идеале, тестируемая система разработана таким образом , что тест повар может быть легко замещен ( впрыскивается ) для работы с официанта без изменения коды производства (например , без изменения коды официанта).
Макет объектов
Теперь тест-кулинар (test double) может быть реализован разными способами:
См. Статью Фаулера для получения более подробной информации о подделках, окурках, фиктивных и манекенах , но сейчас давайте сосредоточимся на фальшивом кулинаре.
Большая часть модульного тестирования компонента официанта фокусируется на том, как официант взаимодействует с компонентом повара. Подход, основанный на имитации, фокусируется на том, чтобы полностью определить, что такое правильное взаимодействие, и определить, когда оно идет не так.
Имитируемый объект заранее знает, что должно происходить во время теста (например, какие вызовы его методов будут вызваны и т. Д.), И имитирующий объект знает, как он должен реагировать (например, какое возвращаемое значение предоставить). Насмешка покажет, отличается ли то, что действительно происходит, от того, что должно произойти. Пользовательский фиктивный объект может быть создан с нуля для каждого тестового примера, чтобы выполнить ожидаемое поведение для этого тестового примера, но фреймворк стремится к тому, чтобы такая спецификация поведения была четко и легко указана непосредственно в тестовом примере.
Разговор о ложном тесте может выглядеть так:
Но так как наш официант новичок, вот что может произойти:
или
Может быть трудно ясно увидеть разницу между фиктивными объектами и заглушками без контрастирующего примера на основе заглушки, но этот ответ уже слишком длинный :-)
Также обратите внимание на то, что это довольно упрощенный пример, и что макеты-фреймворки допускают некоторые довольно сложные спецификации ожидаемого поведения компонентов для поддержки всесторонних тестов. Есть много материала о ложных объектах и насмешливых структурах для получения дополнительной информации.
источник
Mock Object - это объект, который заменяет реальный объект. В объектно-ориентированном программировании фиктивные объекты - это симулированные объекты, которые имитируют поведение реальных объектов контролируемыми способами.
Программист обычно создает фиктивный объект для проверки поведения какого-либо другого объекта, почти так же, как автомобильный конструктор использует манекен для краш-теста для имитации динамического поведения человека при столкновении с транспортным средством.
http://en.wikipedia.org/wiki/Mock_object
Поддельные объекты позволяют вам создавать тестовые сценарии, не используя большие громоздкие ресурсы, такие как базы данных. Вместо вызова базы данных для тестирования, вы можете смоделировать вашу базу данных, используя фиктивный объект в ваших модульных тестах. Это освобождает вас от необходимости устанавливать и разрушать настоящую базу данных, просто чтобы протестировать один метод в вашем классе.
Слово «макет» иногда ошибочно используется как «заглушка». Различия между двумя словами описаны здесь. По существу, макет - это объект-заглушка, который также включает ожидания (то есть «утверждения») для правильного поведения тестируемого объекта / метода.
Например:
Обратите внимание, что объекты
warehouse
иmailer
mock запрограммированы с ожидаемыми результатами.источник
Поддельные объекты - это моделируемые объекты, которые имитируют поведение реальных. Обычно вы пишете фиктивный объект, если:
источник
Объект Mock - это один из видов Test Double . Вы используете mockobjects для тестирования и проверки протокола / взаимодействия тестируемого класса с другими классами.
Как правило, вы будете в некотором роде «программными» или «записывать» ожидания: вызовы методов, которые вы ожидаете, что ваш класс сделает с базовым объектом.
Допустим, например, что мы тестируем сервисный метод для обновления поля в виджете. И что в вашей архитектуре есть WidgetDAO, который имеет дело с базой данных. Разговор с базой данных идет медленно, его настройка и последующая очистка усложняются, поэтому мы смоделируем WidgetDao.
давайте подумаем, что должен делать сервис: он должен получить виджет из базы данных, сделать что-то с ним и сохранить его снова.
Таким образом, в псевдо-языке с псевдо-фиктивной библиотекой у нас будет что-то вроде:
Таким образом, мы можем легко протестировать разработку классов, которые зависят от других классов.
источник
Я настоятельно рекомендую отличную статью Мартина Фаулера, в которой объясняется, что такое макеты и чем они отличаются от заглушек.
источник
При модульном тестировании какой-либо части компьютерной программы в идеале вы хотите протестировать только поведение этой конкретной части.
Например, посмотрите на псевдокод ниже из воображаемого фрагмента программы, которая использует другую программу для вызова функции печати чего-либо:
Если вы тестировали это, вы бы в основном хотели протестировать ту часть, которая проверяет, является ли пользователь Фредом или нет. Вы действительно не хотите проверять
Printer
часть вещей. Это было бы еще одним испытанием.Это то место , где появляются ложные объекты. Они притворяются другими вещами. В этом случае вы бы использовали макет,
Printer
чтобы он действовал так же, как настоящий принтер, но не делал бы неудобных вещей, таких как печать.Есть несколько других типов притворных объектов, которые вы можете использовать, но не Mocks. Главное, что делает Mocks Mocks, - это то, что их можно настроить с учетом поведения и ожиданий.
Ожидания позволяют вашей Mock выдавать ошибку, если она используется неправильно. Таким образом, в приведенном выше примере вы можете быть уверены, что Printer вызывается с HelloFred в тестовом примере "user is Fred". Если этого не произойдет, ваш издеватель может предупредить вас.
Поведение в издевательствах означает, что, например, ваш код сделал что-то вроде:
Теперь вы хотите проверить, что делает ваш код при вызове Printer и возвращает SaidHello, поэтому вы можете настроить Mock на возврат SaidHello при вызове с HelloFred.
Один хороший ресурс вокруг этого Мартин Fowlers разместить Mocks ли не Столбики
источник
Ложные и тупые объекты являются важной частью модульного тестирования. На самом деле они проходят долгий путь, чтобы убедиться, что вы тестируете юниты , а не группы юнитов.
Короче говоря, вы используете заглушки, чтобы сломать зависимость SUT (тестируемая система) от других объектов и макетов, чтобы сделать это, и убедиться, что SUT вызвал определенные методы / свойства для зависимости. Это восходит к фундаментальным принципам модульного тестирования - то, что тесты должны быть легко читаемыми, быстрыми и не требующими настройки, что может подразумевать использование всех реальных классов.
Как правило, в вашем тесте может быть несколько заглушек, но у вас должен быть только один макет. Это потому, что целью макета является проверка поведения, а ваш тест должен проверять только одну вещь.
Простой сценарий с использованием C # и Moq:
В приведенном выше примере я использовал Moq для демонстрации заглушек и насмешек. Moq использует один и тот же класс для обоих -
Mock<T>
что делает его немного запутанным. Независимо от того, во время выполнения, тест не будет выполнен, еслиoutput.Write
не вызывается с данными какparameter
, тогда как неудачный вызовinput.Read()
не провалит его.источник
Как еще один ответ, предложенный через ссылку на « Насмешки не заглушки », mocks - это форма «test double», которую можно использовать вместо реального объекта. Что отличает их от других форм тестовых двойников, таких как объекты-заглушки, заключается в том, что другие тестовые двойники предлагают проверку состояния (и, возможно, моделирование), тогда как макеты предлагают проверку поведения (и, возможно, моделирование).
С заглушкой вы можете вызывать несколько методов заглушки в любом порядке (или даже многократно) и определять успех, если заглушка получила значение или состояние, которое вы намеревались. Напротив, фиктивный объект ожидает вызова очень специфических функций в определенном порядке и даже определенное количество раз. Тест с фиктивным объектом будет считаться «неудачным» просто потому, что методы были вызваны в другой последовательности или количестве - даже если фиктивный объект имел правильное состояние после завершения теста!
Таким образом, фиктивные объекты часто считаются более тесно связанными с кодом SUT, чем объекты-заглушки. Это может быть хорошо или плохо, в зависимости от того, что вы пытаетесь проверить.
источник
Частью использования фиктивных объектов является то, что они не должны быть реально реализованы в соответствии со спецификацией. Они могут просто дать фиктивные ответы. Например, если вам нужно реализовать компоненты A и B, и оба «вызывают» (взаимодействовать) друг с другом, то вы не можете проверить A, пока не будет реализован B, и наоборот. В тестовой разработке это проблема. Таким образом, вы создаете фиктивные («фиктивные») объекты для A и B, которые очень просты, но дают некоторый ответ, когда с ними взаимодействуют. Таким образом, вы можете реализовать и протестировать A, используя фиктивный объект для B.
источник
Для php и phpunit это хорошо объяснено в документации phpunit. смотрите здесь документацию phpunit
В простом слове mocking object - это просто фиктивный объект вашего оригинала, который возвращает свое возвращаемое значение, это возвращаемое значение может быть использовано в тестовом классе
источник
Это одна из основных перспектив юнит-тестов. да, вы пытаетесь протестировать свою единицу кода, и результаты вашего теста не должны быть связаны с поведением других компонентов или объектов. таким образом, вы должны смоделировать их, используя объекты Mock с некоторым упрощенным соответствующим ответом.
источник