Как выполнить модульное тестирование метода с созданием нескольких объектов в операторе switch? Как издеваться над ними? - PullRequest
0 голосов
/ 09 января 2019

Другой вопрос: есть ли лучший способ написать этот метод?

Public decimal CalculateTotalPrice(List<product> items)
{
    decimal totalPrice = 0.m;

    foreach(Product p in items)
    {
        if(p.Offer == "")
            calc = new DefaultCalc();
        else if(p.Offer == "BuyOneGetOneFree")
            calc = new BuyOneGetOneFreeCalc();
        else if(p.Offer == "ThreeInPriceOfTwo")
            calc = new ThreeInPriceOfTwoCalc()

        totalPrice += calc.Calculate(p.Quantity, p.UnitPrice);
    }
    return totalPrice;
}

Ответы [ 3 ]

0 голосов
/ 09 января 2019

Вы, вероятно, должны рассмотреть Полли Хотите сообщение , Сэнди Метц

Как выполнить модульное тестирование метода с созданием нескольких объектов в операторе switch?

Здесь важно отметить, что оператор switch является подробностью реализации . С точки зрения звонящего эта штука просто функция

Public decimal CalculateTotalPrice(List<product> items);

Если расчеты цен являются фиксированными, вы можете просто использовать обычные тесты на основе примеров:

assertEquals(expectedPrice, CalculateTotalPrice(items));

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

  • цена всегда должна быть больше нуля.
  • цена списка товаров равна сумме цен отдельных товаров.

если есть лучший способ написать этот метод?

Вы можете отделить , выбрав стратегию ценообразования от , используя стратегию. Как отмечает Сэнди, такая конструкция часто появляется в нескольких местах.

foreach(Product p in items)
{
    calc = pricing(p.Offer);
    totalPrice += calc.Calculate(p.Quantity, p.UnitPrice);
}

тогда «ценообразование» станет чем-то, что вы передадите в эту функцию (либо как аргумент, либо как зависимость).

По сути, вы получите три разных вида испытаний.

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

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

0 голосов
/ 10 января 2019

Другие ответы технически хороши, но я бы предложил одно:

    if(p.Offer == "")
        calc = new DefaultCalc();
    else if(p.Offer == "BuyOneGetOneFree")
        calc = new BuyOneGetOneFreeCalc();
    else if(p.Offer == "ThreeInPriceOfTwo")
        calc = new ThreeInPriceOfTwoCalc()

должен абсолютно перейти в свой метод / область видимости / что угодно.

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

0 голосов
/ 09 января 2019

Конструкторы не могут быть высмеяны (по крайней мере, с помощью бесплатных рамок для насмешек).

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

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

Подготовить данные

var products = new List<Product>
{
    new Product { Quantity = 10, UnitPrice = 5.0m, Offer = "" },
    new Product { Quantity = 2, UnitPrice = 3.0m , Offer = "BuyOneGetOneFree" },
    new Product { Quantity = 3, UnitPrice = 2.0m , Offer = "ThreeInPriceOfTwo" },
}

// prepare expected total
var expected = 57.0m; // 10 * 50.0 + 1 * 3.0 + 2 * 2.0

// Run the test
var actual = CalculateTotalPrice(products);

actual.Should().Be(expected); // pass Ok.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...