Протестируйте метод, использующий свойство класса - PullRequest
0 голосов
/ 14 июля 2020

Допустим, у меня есть класс, у которого есть метод для чего-то вычислить (неважно какой). Это может выглядеть примерно так:

class Example 
{
    public int CalculateStuff(int inputValue) 
    {
        // ...some logic here
    }
}

Но inputValue всегда берется из самого класса. Вместо этого это могло бы выглядеть так:

class Example
{
    public int InputValue { get; set; }
    
    public int CalculateStuff()
    {
        // ...calculate something from 'InputValue'
    }
}

Отлично, но я хотел бы добавить модульный тест к CalculateStuff(), поэтому вот мой вопрос:

What лучший способ сделать четкий тест? Я мог бы просто установить значение класса в тесте, например:

void UnitTest()
{
     var example = new Example();
     example.InputValue = 42;
     Assert.AreEqual(84, example.CalculateStuff());
}

Однако я мог бы также создать метод CalculateStuff() a static с нестатической c перегрузкой, а затем протестируйте часть stati c. Преимущество этого (насколько я могу судить) заключается в том, что он также будет работать в сценарии, где InputValue - это что-то вроде DateTime.Now:

class Example
{
    public int InputValue { get; set; }
    
    public int CalculateStuff()
    {
        return CalculateStuff(InputValue);
    }

    public static int CalculateStuff(int inputValue)
    {
        // ...calculate something from 'inputValue'
    }
}

void UnitTest()
{
    Assert.AreEqual(84, Example.CalculateStuff(42));
}

Есть ли широко распространенный способ сделать это ? И если да, то какие? Или это зависит от конкретного случая c?

Обновление

Другой пример, который немного отличается (но в той же категории), если вход был типа DateTime, который в производстве всегда использовал DateTime.Now в качестве входных данных (например, для вычисления времени с момента некоторого события). Это означало бы, что класс Example всегда имел свойство со значением DateTime.Now, если следовать первому подходу:

public int CalculateDateStuff(DateTime untilDtm) 
{
    // ...logic and stuff
}

, которое затем вызывается следующим образом:

var result = example.CalculateDateStuff(DateTime.Now);

... по крайней мере, если это должно быть проверено.

Ответы [ 3 ]

1 голос
/ 14 июля 2020

Вы не должны добавлять дополнительные методы, просто для тестирования других методов. То, что вы делаете, правильно. Как правило, модульный тест состоит из 3 шагов (названия шагов могут отличаться):

  1. Настройка: Подготовьте все необходимое для ваших тестов.
  2. Действие: Запустите метод, который вы хотите test.
  3. Assert: проверьте результат действий относительно ожидаемого результата.

В вашем случае:

void UnitTest()
{
    //Setup
    var example = new Example();
    example.InputValue = 42;

    //Action
    var result = example.CalculateStuff()

    //Assert
    Assert.AreEqual(84, result);
}
0 голосов
/ 14 июля 2020

четкий тест может быть написан только в том случае, если у вас есть четкий код.

ваш первый пример, в котором вы передаете то, что необходимо вашему методу, - самый простой способ сделать это.

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

Что касается других типов данных, таких как DateTime, ответ такой же, ваше значение datetime является параметром, и вы можете передать DateTime.Now своему методу.

Итог, если бы у меня был выбор, я бы все время придерживался этой конструкции:

public int CalculateStuff(int inputValue) 
    {
        // ...some logic here
    }
0 голосов
/ 14 июля 2020

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

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

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

Представьте себе случай в у вас есть 10 свойств и 10 методов: насколько может вырасти этот класс?

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