В чем разница между макетом и заглушкой? - PullRequest
817 голосов
/ 11 августа 2010

Я читал различные статьи о насмешках против окурков в тестировании, в том числе Насмешки Мартина Фаулера не являются заглушками , но до сих пор не понимаю разницу.

Ответы [ 35 ]

4 голосов
/ 22 января 2017

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

4 голосов
/ 01 января 2014

Смотрите ниже пример mocks против заглушек с использованием C # и Moq framework.В 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";
        }
    }
}
3 голосов
/ 23 марта 2019

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

enter image description here

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

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

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

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

Подробнее здесь и здесь

3 голосов
/ 30 ноября 2013

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

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

2 голосов
/ 21 декабря 2016

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

2 голосов
/ 13 декабря 2014

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

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 , примечание в mock для python 2.x не входит в unittest, но является загружаемым модулем, который можно загрузить через pip (pip install mock).

Я также прочитал «Искусство модульного тестирования» Роя Ошерова, и я думаю, было бы здорово, если бы подобная книга была написана с использованием примеров Python и Python. Если кто-нибудь знает о такой книге, пожалуйста, поделитесь. Ура :) 1024 *

2 голосов
/ 18 декабря 2017

много правильных ответов, но я думаю, стоит упомянуть эту форму, дядя Боб: https://8thlight.com/blog/uncle-bob/2014/05/14/TheLittleMocker.html

лучшее объяснение с примерами!

2 голосов
/ 23 июня 2015

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

function foo(){}

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

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

С точки зрения утверждений и состояния:

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

Ссылки

1 голос
/ 23 января 2015

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

модульный тест -> заглушка

юнит тест -> юнит -> заглушка

единичный тест подтверждает результаты и состояние единицы

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

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

модульный тест -> макет

юнит тест -> юнит -> макет

единичный тест подтверждает результат и состояние единицы

модульный тест подтверждает методы, вызываемые на mock

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

0 голосов
/ 26 мая 2019

И заглушки, и макеты перекрывают внешние зависимости, но разница составляет

Заглушки -> Для проверки данных

Mocks -> для проверки поведения


Fake / Dummy -> Ничего не проверяется (просто переопределите функциональность пустыми методами, например, замените Logger, чтобы избежать шума при регистрации во время тестирования)

...