В чем разница между фальсификацией, насмешкой и ступлением?

Я знаю, как я использую эти термины, но мне интересно, приняты ли определения для фальсификации , издевательств и stubbing для модульных тестов? Как вы определяете их для своих тестов? Опишите ситуации, в которых вы можете использовать каждый.

Вот как я их использую:

Fake : class, который реализует интерфейс, но содержит фиксированные данные и никакой логики. Просто возвращает «хорошие» или «плохие» данные в зависимости от реализации.

Mock : class, который реализует интерфейс и позволяет динамически устанавливать значения для возврата / исключений, чтобы выбрасывать из определенных методов и предоставляет возможность проверить, были ли вызваны / не вызваны определенные методы.

Штук : как class макета, за исключением того, что он не дает возможности проверить, что методы были вызваны / не вызваны.

Мошки и заглушки могут быть сгенерированы или сгенерированы с помощью насмешливой структуры. Поддельные classы создаются вручную. Я использую mocks прежде всего для проверки взаимодействия между моим classом и зависимыми classами. Я использую заглушки, когда я проверил взаимодействия и тестирую альтернативные пути через свой код. Я использую поддельные classы, прежде всего, для абстрагирования зависимостей данных или когда mocks / stub слишком утомительны для настройки каждый раз.

Вы можете получить некоторую информацию:

От Мартина Фаулера о Mock и Stub

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

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

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

От xunitpattern :

Fake : Мы приобретаем или создаем очень легкую реализацию тех же функций, что и компонент, на который зависит SUT, и инструктируйте SUT использовать его вместо реального.

Штук : эта реализация настроена так, чтобы отвечать на вызовы от SUT со значениями (или исключениями), которые будут использовать неактивный код (см. «Производственные ошибки на странице X») в SUT. Ключевым показанием для использования тестового заглушки является непроверенный код, вызванный невозможностью управления косвенными входами SUT

Mock Object, который реализует тот же интерфейс, что и объект, на котором зависит SUT (System Under Test). Мы можем использовать Mock Object в качестве точки наблюдения, когда нам нужно выполнить проверку поведения, чтобы избежать наличия непроверенных требований (см. «Ошибки производства на странице X»), вызванные неспособностью наблюдать побочные эффекты методов вызова на SUT.

Лично

Я пытаюсь упростить, используя: Mock и Stub. Я использую Mock, когда это объект, который возвращает значение, установленное для тестируемого classа. Я использую Stub для имитации интерфейса или абстрактного classа для тестирования. Фактически, на самом деле не имеет значения, как вы это называете, все classы, которые не используются в производстве, и используются в качестве служебных classов для тестирования.

Stub – объект, который предоставляет предопределенные ответы на вызовы методов.

Mock – объект, на который вы устанавливаете ожидания.

Fake – объект с ограниченными возможностями (для целей тестирования), например, поддельный веб-сервис.

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

Я удивлен, что этот вопрос существует так долго, и никто пока не получил ответа, основанного на «Тестировании единиц измерения» Роя Ошерова .

В «3.1 Знакомство с заглушками» определяет заглушку как:

Штук – это контролируемая замена существующей зависимости (или соавтора) в системе. Используя заглушку, вы можете протестировать свой код, не обращаясь напрямую к зависимости.

И определяет разницу между заглушками и mocks как:

Главное, чтобы помнить о насмешках и окурках, – это то, что издевательства похожи на окурки, но вы утверждаете против макетного объекта, тогда как вы не утверждаете против заглушки.

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

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

  • Когда ваш тест проверяет значения в тестируемом classе или фактически где-либо, кроме фальшивки, подделка использовалась в качестве заглушки. Он просто предоставил значения для тестируемого classа, либо непосредственно через значения, возвращаемые вызовами, либо косвенно, вызывая побочные эффекты (в некотором состоянии) в результате вызовов на нем.
  • Когда ваш тест проверяет значения подделки, он использовался как макет.

Пример теста, в котором class FakeX используется как заглушка:

const pleaseReturn5 = 5; var fake = new FakeX(pleaseReturn5); var cut = new ClassUnderTest(fake); cut.SquareIt; Assert.AreEqual(25, cut.SomeProperty); 

fake экземпляр используется как заглушка, потому что Assert не использует fake вообще.

Пример теста, в котором тестовый class X используется как макет:

 const pleaseReturn5 = 5; var fake = new FakeX(pleaseReturn5); var cut = new ClassUnderTest(fake); cut.SquareIt; Assert.AreEqual(25, fake.SomeProperty); 

В этом случае Assert проверяет значение на fake , делая этот поддельный макет.

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

Я согласен с Ошеровым в том, что

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

Утверждение против подделки – это то, чего вы действительно хотите избежать, поскольку это заставляет ваши тесты сильно зависеть от реализации classа, который не является тестируемым вообще. Это означает, что тесты для classа ActualClassUnderTest могут начать ломаться, потому что реализация для ClassUsedAsMock изменилась. И это посылает мне неприятный запах. Тесты для ActualClassUnderTest должны предпочтительно прерываться только при изменении ActualClassUnderTest .

Я понимаю, что написание утверждений против подделки – обычная практика, особенно когда вы являетесь поддельным типом подписчика TDD. Наверное, я твердо придерживаюсь Мартина Фаулера в classицистском лагере (см . «Моки» Мартина Фаулера ), и, как и Ошерове, избегайте тестирования взаимодействия (которое может быть сделано только путем утверждения против подделки) в максимально возможной степени.

Для забавного чтения о том, почему вы должны избегать издевательств, как определено здесь, google для «фауниста-classика-москиста». Вы найдете множество мнений.

Чтобы проиллюстрировать использование заглушек и макетов, я хотел бы также привести пример, основанный на « Тестировании единиц измерения » Роя Ошероу.

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

Вот логика, которую мы хотели бы протестировать внутри LogAnalyzer:

 if(fileName.Length<8) { try { service.LogError("Filename too short:" + fileName); } catch (Exception e) { email.SendEmail("a","subject",e.Message); } } 

Как вы проверяете, правильно ли LogAnalyzer вызывает службу электронной почты, когда веб-служба выдает исключение? Вот вопросы, с которыми мы сталкиваемся:

  • Как мы можем заменить веб-сервис?

  • Как мы можем имитировать исключение из веб-службы, чтобы мы могли протестировать вызов в службу электронной почты?

  • Как мы узнаем, что служба электронной почты была вызвана правильно или вообще?

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

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

 [TestFixture] public class LogAnalyzer2Tests { [Test] public void Analyze_WebServiceThrows_SendsEmail() { StubService stubService = new StubService(); stubService.ToThrow= new Exception("fake exception"); MockEmailService mockEmail = new MockEmailService(); LogAnalyzer2 log = new LogAnalyzer2(); log.Service = stubService log.Email=mockEmail; string tooShortFileName="abc.ext"; log.Analyze(tooShortFileName); Assert.AreEqual("a",mockEmail.To); //MOCKING USED Assert.AreEqual("fake exception",mockEmail.Body); //MOCKING USED Assert.AreEqual("subject",mockEmail.Subject); } } 

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

Я знаком с Arrange-Act-Assert, тогда один из способов объяснить разницу между заглушкой и макетом, которые могут быть полезны для вас, заключается в том, что заглушки принадлежат к разделу «Аранжировка», поскольку они предназначены для организации входного состояния, а mocks принадлежат секция утверждения, поскольку они предназначены для утверждения результатов против.

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

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

  • Что такое управляемый / неуправляемый код на C #?
  • Weird undefined символы статических констант внутри struct / class
  • Какое определение «интерфейс» в объектно-ориентированном программировании
  • Почему избыточная квалификация, поддерживаемая компилятором, является законной?
  • Каков пример Принципа замещения Лискова?
  • Что такое «Currying»?
  • Каков пример принципа единой ответственности?
  • Используется ли для объявлений локальных функций?
  • Что это за синтаксис определения странных функций в C?
  • Haskell: Что такое нормальная форма слабой головы?
  • Что такое «stream» (действительно)?
  • Давайте будем гением компьютера.