Какая разница между макетами и заглушками?

Я читал различные статьи о насмешливых vs stubbing в тестировании, в том числе Мартин Фаулер Mocks не ноты, но все равно не понимают разница.

Ответ 1

огрызок

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

издеваться

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

Разница между издевательствами и окурками

Тесты, написанные с помощью макетов, обычно следуют за initialize → set expectations → exercise → verify шаблона для тестирования. В то время как предварительно написанная заглушка будет следовать за initialize → exercise → verify.

Сходство между издевательствами и окурками

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

Ответ 2

Предисловие

Существует несколько определений объектов, которые не являются реальными. Общий термин test double. Этот термин включает в себя: фиктивный, поддельный, заглушка, макет.

Ссылка

Согласно статья Мартина Фаулера:

  • Объекты
  • Dummy передаются, но никогда не используются. Обычно они просто используются для заполнения списков параметров.
  • Фальшивые объекты фактически имеют рабочие реализации, но обычно берут некоторый ярлык, что делает их непригодными для производства (в базе данных данных - хороший пример).
  • Stubs предоставляют консервированные ответы на вызовы, сделанные во время теста, обычно вообще не реагируют на что-либо вне того, что запрограммировано для теста. Stubs также может записывать информацию о вызовах, таких как заглушка шлюза электронной почты, которая запоминает отправленные сообщения, или, может быть, только то, сколько сообщений отправлено ".
  • Mocks - это то, о чем мы говорим здесь: объекты, предварительно запрограммированные с ожиданиями, которые формируют спецификацию ожидаемых вызовов.

Стиль

Mocks vs Stubs = Поведенческое тестирование vs State testing

Принцип

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

Lifecycle

Жизненный цикл тестирования с заглушками:

  • Настройка - Подготовьте тестируемый объект и его коллабораторы.
  • Упражнение - проверьте функциональность.
  • Проверить состояние - использовать утверждения для проверки состояния объекта.
  • Teardown - очистка ресурсов.

Жизненный цикл тестирования с помощью mocks:

  • Данные настройки - Подготовьте тестируемый объект.
  • Ожидания настройки. Подготовьте ожидания в макете, который используется основным объектом.
  • Упражнение - проверьте функциональность.
  • Проверить ожидания. Убедитесь, что правильные методы были вызваны в mock.
  • Проверить состояние - использовать утверждения для проверки состояния объекта.
  • Teardown - очистка ресурсов.

Резюме

Оба теста mocks и stubs дают ответ на вопрос: Каков результат?

Тестирование с помощью mocks также интересует: Как результат был достигнут?

Ответ 3

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

Ответ 4

Вот описание каждого из них, за которым следует образец реального мира.

  • Dummy - просто фиктивные значения, удовлетворяющие API.

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

  • Fake - создать тестовую реализацию класса, который может иметь зависимость от некоторой внешней инфраструктуры. (Хорошей практикой является то, что ваш unit test действительно НЕ взаимодействует с внешней инфраструктурой.)

    Пример: создайте поддельную реализацию для доступа к базе данных, замените ее на коллекцию in-memory.

  • Stub - переопределить методы для возврата жестко заданных значений, также называемых state-based.

    Пример: ваш тестовый класс зависит от метода Calculate(), который занимает 5 минут. Вместо того, чтобы ждать 5 минут, вы можете заменить его реальную реализацию заглушкой, которая возвращает жестко заданные значения; занимая лишь небольшую часть времени.

  • Mock - очень похоже на Stub, но interaction-based, а не на основе состояния. Это означает, что вы не ожидаете от Mock возврата некоторого значения, но предположим, что выполняется конкретный порядок вызовов методов.

    Пример. Вы тестируете класс регистрации пользователя. После вызова Save он должен вызвать SendConfirmationEmail.

Stubs и Mocks на самом деле являются подтипами Mock, обе реализуют реальную реализацию с реализацией теста, но по разным причинам.

Ответ 5

В codeschool.com курсе Rails Testing for Zombies они дают это определение терминов

Заглушка

Для замены метода кодом, который возвращает указанный результат.

Тестовая модель

Замыкание с утверждением, что метод вызван.

Так как Шон Копенгавер описал в своем ответе, разница в том, что издеваются над ожиданиями (т.е. делают утверждения, о том, вызваны ли они или как они вызваны).

Ответ 6

Штыри не терпят неудачу в тестах, но могут ошибаться.

Ответ 7

Я думаю, что самый простой и ясный ответ на этот вопрос дан из Роя Ошерова в его книге Искусство модульного тестирования (стр. 85)

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

С другой стороны, тест будет использовать макет объекта для проверки того, тест не выполнен или нет. [...]

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

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

Ответ 8

Читая все объяснения выше, позвольте мне попытаться конденсироваться:

  • Штук: фиктивный кусок кода, который позволяет пройти тест, но вам все равно, что с ним происходит.
  • Макет: фиктивный кусок кода, который вы VERIFY называете правильным как часть теста.
  • Spy: кусочек кода, который перехватывает некоторые вызовы на реальный фрагмент кода, позволяя вам проверять вызовы без замены всего исходного объекта.

Ответ 9

Mock - это просто проверка поведения, следя за тем, чтобы вызывались определенные методы. A Stub - проверяемая версия (как таковая) конкретного объекта.

Что вы подразумеваете под Apple?

Ответ 10

Если вы сравните его с отладкой:

Stub похож на то, что метод возвращает правильное значение

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

Ответ 11

Я думаю, что самое важное различие между ними - их намерения.

Позвольте мне объяснить это в WHY stub против ПОЧЕМУ mock

Предположим, что я пишу тестовый код для моего клиентского контроллера общей статистики клиента Twitter twitter

Вот пример тестового кода

twitter_api.stub(:public_timeline).and_return(public_timeline_array)
client_ui.should_receive(:insert_timeline_above).with(public_timeline_array)
controller.refresh_public_timeline
  • STUB: Сетевое подключение к API twitter очень медленное, что замедляет мой тест. Я знаю, что он вернет временные рамки, поэтому я сделал stub, имитирующий HTTP twitter API, так что мой тест будет работать очень быстро, и я могу запустить тест, даже если я в автономном режиме.
  • MOCK: Я еще не написал ни одного из моих методов пользовательского интерфейса, и я не уверен, какие методы мне нужно написать для моего объекта ui. Я надеюсь узнать, как мой контроллер будет взаимодействовать с моим объектом ui, написав тестовый код.

Написав mock, вы обнаружите взаимосвязь между отношениями объектов, проверив ожидание, а stub только имитирует поведение объекта.

Я предлагаю прочитать эту статью, если вы хотите узнать больше о mocks: http://jmock.org/oopsla2004.pdf

Ответ 12

Быть предельно ясным и практичным:

Stub: класс или объект, который реализует методы класса/объекта, подлежащего подделке, и возвращает всегда то, что вы хотите.

Пример в JavaScript:

var Stub = {
   method_a: function(param_a, param_b){
      return 'This is an static result';
   }
}

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

Как говорит @mLevan, представьте, что вы тестируете класс регистрации пользователя. После вызова "Сохранить" он должен вызвать SendConfirmationEmail.

Очень глупый код Пример:

var Mock = {
   calls: {
      method_a: 0
   }

   method_a: function(param_a, param_b){
     this.method_a++; 
     console.log('Mock.method_a its been called!');
   }
}

Ответ 13

Этот слайд объясняет основные различия очень хорошо.

введите описание изображения здесь

* Из CSE 403 Лекция 16, Вашингтонский университет (слайд, созданный "Марти Степп" )

Ответ 14

Использование ментальной модели действительно помогло мне понять это, а не все объяснения и статьи, которые не совсем "утонули".

Представьте, что у вашего ребенка на столе стеклянная тарелка, и он начинает с ней играть. Теперь вы боитесь, что оно сломается. Итак, вместо этого вы даете ему пластиковую тарелку. Это будет Mock (такое же поведение, тот же интерфейс, "более мягкая" реализация).

Теперь, скажем, у вас нет замены пластика, поэтому вы объясняете: "Если вы продолжите играть с ним, он сломается!". Это заглушка, вы заранее указали заранее заданное состояние.

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

Ответ 15

Мне нравится объяснение, высказанное Роем Ошеровом [видео ссылка].

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

Ответ 16

  • Забастовки против Mocks
    • Столбики
      1. предоставлять конкретные ответы на вызовы методов
        • ex: myStubbedService.getValues() просто возвращает строку, требуемую тестируемым кодом
      2. используется для тестирования кода для изоляции
      3. не может потерпеть неудачу
        • ex: myStubbedService.getValues() просто возвращает заштрихованное значение
      4. часто реализуют абстрактные методы
    • Mocks
      1. "надмножество" заглушек; может утверждать, что определенные методы называются
        • ex: убедитесь, что myMockedService.getValues() вызывается только один раз
      2. используется для проверки поведения тестируемого кода
      3. может выйти из строя
        • ex: убедитесь, что myMockedService.getValues() был вызван один раз; проверка завершилась неудачно, поскольку myMockedService.getValues() не был вызван моим проверенным кодом
      4. часто издевается над интерфейсами

Ответ 17

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

Является ли подделка заглушкой или макетом, зависит от того, как она используется в текущий тест. Если он используется для проверки взаимодействия (утверждается против), его макет объекта. В противном случае его заглушка.

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

Что означает тестовый запуск?
Например, ниже код:

 public void Analyze(string filename)
        {
            if(filename.Length<8)
            {
                try
                {
                    errorService.LogError("long file entered named:" + filename);
                }
                catch (Exception e)
                {
                    mailService.SendEMail("[email protected]", "ErrorOnWebService", "someerror");
                }
            }
        }

Вы хотите протестировать метод mailService.SendEMail(), чтобы сделать это для симуляции исключения в вашем тестовом методе, поэтому вам просто нужно создать класс Fake Stub errorService для имитации этого результата, тогда ваш тестовый код будет способный проверить метод mailService.SendEMail(). Как вы видите, вам нужно смоделировать результат, который является результатом другого класса External Dependency ErrorService.

Ответ 18

давайте посмотрим тест двойников:

  • Подделка: Подделки - это объекты, которые имеют рабочие реализации, но не совпадают с производственными. Такие как: реализация в памяти объекта доступа к данным или репозитория.
  • Stub: Stub - это объект, который содержит предопределенные данные и использует их для ответа на вызовы во время тестов. Например: объект, который должен получить некоторые данные из базы данных, чтобы ответить на вызов метода.

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

Ответ 19

Справа от статьи Определить роли, а не объекты, разработчиками jMock:

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

Итак, основные отличия:

  • ожидания, установленные на заглушках, обычно являются общими, в то время как ожидания, установленные на mocks, могут быть более "умными" (например, вернуть это при первом вызове, это на втором и т.д.).
  • stubs используются главным образом для настройки косвенных входов SUT, а mocks можно использовать для тестирования как косвенных входов, так и косвенные выходы SUT.

Подводя итог, также пытаясь разогнать путаницу из статья Фаулера: mocks - это заглушки, но они не только окурки.

Ответ 20

См. ниже пример mocks vs stubs с использованием С# и рамки Moq. Moq не имеет специального ключевого слова для Stub, но вы также можете использовать Mock-объект для создания заглушек.

namespace UnitTestProject2
{
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moq;
    [TestClass]
    public class UnitTest1
    {
        /// <summary>
        /// Test using Mock to Verify that GetNameWithPrefix method calls Repository GetName method "once" when Id is greater than Zero
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsTwelve_GetNameCalledOnce()
        {
            // Arrange 
            var mockEntityRepository = new Mock<IEntityRepository>();
            mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));

            var entity = new EntityClass(mockEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(12);
            // Assert
            mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Once);
        }
        /// <summary>
        /// Test using Mock to Verify that GetNameWithPrefix method doesn't call Repository GetName method when Id is Zero
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsZero_GetNameNeverCalled()
        {
            // Arrange 
            var mockEntityRepository = new Mock<IEntityRepository>();
            mockEntityRepository.Setup(m => m.GetName(It.IsAny<int>()));
            var entity = new EntityClass(mockEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(0);
            // Assert
            mockEntityRepository.Verify(m => m.GetName(It.IsAny<int>()), Times.Never);
        }
        /// <summary>
        /// Test using Stub to Verify that GetNameWithPrefix method returns Name with a Prefix
        /// </summary>
        [TestMethod]
        public void GetNameWithPrefix_IdIsTwelve_ReturnsNameWithPrefix()
        {
            // Arrange 
            var stubEntityRepository = new Mock<IEntityRepository>();
            stubEntityRepository.Setup(m => m.GetName(It.IsAny<int>()))
                .Returns("Stub");
            const string EXPECTED_NAME_WITH_PREFIX = "Mr. Stub";
            var entity = new EntityClass(stubEntityRepository.Object);
            // Act 
            var name = entity.GetNameWithPrefix(12);
            // Assert
            Assert.AreEqual(EXPECTED_NAME_WITH_PREFIX, name);
        }
    }
    public class EntityClass
    {
        private IEntityRepository _entityRepository;
        public EntityClass(IEntityRepository entityRepository)
        {
            this._entityRepository = entityRepository;
        }
        public string Name { get; set; }
        public string GetNameWithPrefix(int id)
        {
            string name = string.Empty;
            if (id > 0)
            {
                name = this._entityRepository.GetName(id);
            }
            return "Mr. " + name;
        }
    }
    public interface IEntityRepository
    {
        string GetName(int id);
    }
    public class EntityRepository:IEntityRepository
    {
        public string GetName(int id)
        {
            // Code to connect to DB and get name based on Id
            return "NameFromDb";
        }
    }
}

Ответ 21

Я наткнулся на эту интересную статью от UncleBob The Little Mocker. Это объясняет всю терминологию очень легко понять, поэтому она полезна для новичков. Статья Мартина Фаулерса читается специально для начинающих, таких как я.

Ответ 22

Стойка для тестирования с заглушкой и макетом:

  • Stub - это фиктивная реализация, выполняемая пользователем статическим способом, т.е. в Stub, записывающая код реализации. Таким образом, он не может обрабатывать определение сервиса и динамическое состояние. Обычно это выполняется в рамках JUnit без использования насмешливой структуры.

  • Mock - также фиктивная реализация, но ее реализация выполнена динамически, используя Mocking frameworks, такие как Mockito. Таким образом, мы можем справиться с определением условий и сервисов как динамическим способом, т.е. Mocks может динамически создаваться из кода во время выполнения. Таким образом, используя mock, мы можем динамически создавать Stubs.

Ответ 23

Stub помогает нам запустить тест. Как? Он дает значения, которые помогают запустить тест. Эти значения сами по себе не являются реальными, и мы создали эти значения только для запуска теста. Например, мы создаем HashMap, чтобы дать нам значения, похожие на значения в таблице базы данных. Поэтому вместо прямого взаимодействия с базой данных мы взаимодействуем с Hashmap.

Mock - это поддельный объект, который запускает тест. где мы положим assert.

Ответ 24

Пример Мокито

enter image description here

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

Макет объекта предоставляет способ проверить, вызывал ли тестируемый объект определенные методы.

И, как сказал Мартин Фаулер в своем эссе

Разница в том, что stub использует проверку состояния, а mock проверку поведения.

Узнайте больше здесь и здесь

Ответ 25

Я использовал примеры python в своем ответе, чтобы проиллюстрировать различия.

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

class Foo(object):
    def bar1(self):
        pass

    def bar2(self):
        #or ...
        raise NotImplementedError

    def bar3(self):
        #or return dummy data
        return "Dummy Data"
Объекты

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

mymodule.py:

import os
import os.path

def rm(filename):
    if os.path.isfile(filename):
        os.remove(filename)

test.py:

from mymodule import rm
import mock
import unittest

class RmTestCase(unittest.TestCase):
    @mock.patch('mymodule.os')
    def test_rm(self, mock_os):
        rm("any path")
        # test that rm called os.remove with the right parameters
        mock_os.remove.assert_called_with("any path")

if __name__ == '__main__':
    unittest.main()

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

Подробнее о unittest.mock, заметьте в python 2.x mock не включен в unittest, а является загружаемым модулем, который можно загрузить через pip (pp install mock).

Я также читал "The Art of Unit Testing" Роя Ошерове, и я думаю, было бы здорово, если бы подобная книга была написана с использованием примеров Python и Python. Если кто-нибудь знает такую ​​книгу, пожалуйста, разделите. Приветствия:)

Ответ 26

Штук - это пустая функция, которая используется во избежание необработанных исключений во время тестов:

function foo(){}

Макет - это искусственная функция, которая используется для предотвращения зависимостей ОС, окружения или оборудования во время тестов:

function foo(bar){ window = this; return window.toString(bar); }

В терминах утверждений и состояний:

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

Ссылки

Ответ 27

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

Ответ 29

A Stub - это объект, который реализует интерфейс компонента, но вместо того, чтобы возвращать то, что компонент будет возвращать при вызове, заглушку можно настроить для возврата значения, которое соответствует тесту. Использование заглушек unit test может проверить, может ли блок обрабатывать различные возвращаемые значения от своего соавтора. Использование заглушки вместо реального соавтора в unit test может быть выражено следующим образом:

unit test → заглушка

unit test → unit → stub

unit test утверждает результаты и состояние единицы

Сначала unit test создает заглушку и настраивает возвращаемые значения. Затем unit test создает блок и устанавливает на него заглушку. Теперь unit test вызывает устройство, которое в свою очередь вызывает заглушку. Наконец, unit test делает утверждения о результатах вызова метода на единицу.

Макет похож на заглушку, только он также имеет методы, которые позволяют определить, какие методы вызывают в Mock. Используя макет, можно, таким образом, проверить, правильно ли устройство может обрабатывать различные возвращаемые значения, а также если устройство правильно использует соавтор. Например, вы не можете увидеть значение, возвращаемое с объекта dao, если данные были прочитаны из базы данных с помощью Statement или PreparedStatement. Также вы не видите, был ли вызван метод connection.close() перед возвратом значения. Это возможно с издевательствами. Другими словами, mocks позволяет тестировать полное взаимодействие блоков с сотрудником. Не только методы соавтора, возвращающие значения, используемые устройством. Использование макета в unit test может быть выражено следующим образом:

unit test → mock

unit test → unit → mock

unit test утверждает результат и состояние единицы

unit test утверждает методы, называемые mock

Подробнее → Здесь

Ответ 30

Следующее - мое понимание...

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

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