Единичное тестирование недействительных методов?

Каков наилучший способ unit test метода, который ничего не возвращает? В частности, в С#.

То, что я действительно пытаюсь проверить, - это метод, который принимает файл журнала и анализирует его для определенных строк. Затем строки вставляются в базу данных. Ничего, что не было сделано раньше, но было ОЧЕНЬ новым для TDD. Мне интересно, можно ли это проверить или это то, что действительно не тестируется.

Ответ 1

Если метод ничего не возвращает, он либо один из следующих

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

Императивные методы - вы можете проверить, действительно ли выполнялась задача. Проверьте, действительно ли произошло изменение состояния. например.

void DeductFromBalance( dAmount ) 

можно проверить, проверив, действительно ли баланс отправляет это сообщение, чем начальное значение dAmount

Информационные методы - редки как член публичного интерфейса объекта... следовательно, обычно не проверяются на единицу. Однако, если необходимо, вы можете проверить, выполняется ли обработка с уведомлением. например.

void OnAccountDebit( dAmount )  // emails account holder with info

можно проверить, проверяя, отправляется ли электронное письмо

Опубликуйте более подробную информацию о вашем фактическом методе, и люди смогут лучше ответить.
Обновить. Ваш метод выполняет 2 действия. Я бы фактически разделил его на два метода, которые теперь могут быть независимо протестированы.

string[] ExamineLogFileForX( string sFileName );
void InsertStringsIntoDatabase( string[] );

String [] легко проверить, предоставив первый метод с фиктивным файлом и ожидаемыми строками. Второй из них немного сложный. Вы можете использовать Mock (google или search stackoverflow на насмешливых фреймворках), чтобы имитировать БД или попасть в фактический БД и проверить, были ли строки вставлены в нужное место. Проверьте эту нить для некоторых хороших книг... Я бы пересмотрел прагматический unit тест, если вы в хрусте.
В коде он будет использоваться как

InsertStringsIntoDatabase( ExamineLogFileForX( "c:\OMG.log" ) );

Ответ 2

Проверьте свои побочные эффекты. Это включает в себя:

  • Выбрасывают ли какие-либо исключения? (Если это так, убедитесь, что это так. Если это не так, попробуйте некоторые угловые случаи, которые могут возникнуть, если вы не будете осторожны - нулевые аргументы являются наиболее очевидными.)
  • Отличается ли он своими параметрами? (Если они изменчивы, они мутируют их, когда это не так, и наоборот?)
  • Имеет ли это право на состояние объекта/типа, на которое вы его вызываете?

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

Ответ 3

Как всегда: проверьте, что должен делать этот метод!

Должно ли это изменить глобальное состояние (уху, запах кода!)?

Должен ли он вызвать интерфейс?

Должен ли он вызывать исключение при вызове с неправильными параметрами?

Должен ли он вызывать исключение при вызове с правильными параметрами?

Должен ли он...?

Ответ 4

Типы возврата Void/Подпрограммы - это старые новости. Я не сделал тип возврата Пустоты (если только не был очень ленив), как 8 лет (со времени ответа, так что немного раньше, чем этот вопрос был задан).

Вместо метода вроде:

public void SendEmailToCustomer()

Сделайте метод, следующий за Microsoft int.TryParse() парадигмой:

public bool TrySendEmailToCustomer()

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

Кроме того, bool не является единственным типом состояния. Существует несколько раз, когда ранее выполненная подпрограмма могла фактически возвращать три или более разных состояния (Хорошие, Нормальные, Плохие и т.д.). В этих случаях вы просто используете

public StateEnum TrySendEmailToCustomer()

Однако, хотя Try-Paradigm несколько отвечает на этот вопрос о том, как проверить возврат void, есть и другие соображения. Например, во время/после цикла "TDD" вы будете "Рефакторинг" и обратите внимание, что вы делаете две вещи своим методом... таким образом, нарушая "принцип единой ответственности". Поэтому сначала нужно позаботиться. Во-вторых, вы могли бы идентифицировать зависимость... вы касаетесь "постоянных" данных.

Если вы делаете материал доступа к данным в методе в вопросе, вам необходимо реорганизовать его в n-уровневую или n-мерную архитектуру. Но мы можем предположить, что когда вы говорите: "Строки затем вставляются в базу данных", вы на самом деле имеете в виду, что вы вызываете уровень бизнес-логики или что-то в этом роде. Я., предположим, что.

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

public <Constructor/MethodName> (IBusinessDataEtc otherLayerOrTierObject, string[] stuffToInsert)

Теперь, когда вы можете принять интерфейс вашего объекта бизнес/уровня данных, вы можете издеваться над ним во время тестов Unit и не иметь никаких зависимостей или страха перед тестированием интеграции "случайно".

Итак, в вашем живом коде вы передаете объект REAL IBusinessDataEtc. Но в вашем тестировании устройств вы передаете объект MOCK IBusinessDataEtc. В этом Mock вы можете включить Неинтерфейсные свойства, такие как int XMethodWasCalledCount или что-то, состояние которых обновляется при вызове методов интерфейса.

Итак, ваш Unit Test будет проходить через ваш метод -In-Question, выполнять любую логику, которую они имеют, и вызывать один или два или выбранный набор методов в вашем объекте IBusinessDataEtc. Когда вы выполняете свои утверждения в конце вашего Unit Test, у вас есть несколько вещей, чтобы протестировать сейчас.

  • Состояние "Подпрограммы", которое теперь является методом Try-Paradigm.
  • Состояние вашего объекта Mock IBusinessDataEtc.

Для получения дополнительной информации о идеях инжекции зависимостей на уровне строительства... поскольку они относятся к тестированию устройств... посмотрите на шаблоны проектирования Builder. Он добавляет еще один интерфейс и класс для каждого текущего интерфейса/класса, который у вас есть, но они очень крошечные и обеспечивают увеличение производительности HUGE для лучшего тестирования Unit.

Ответ 5

он будет иметь некоторое влияние на объект.... запрос для результата эффекта. Если он не имеет видимого эффекта, его не стоит тестировать на единицу!

Ответ 6

Предположительно метод что-то делает и не просто возвращает?

Предполагая, что это так, тогда:

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

Если вы сообщите нам, что делает этот метод, я мог бы быть более конкретным.

Ответ 7

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

Ответ 8

Зависит от того, что он делает. Если у него есть параметры, перейдите в mocks, которые вы могли бы попросить позже, если они были вызваны с правильным набором параметров.

Ответ 9

Попробуйте следующее:

[TestMethod]
public void TestSomething()
{
    try
    {
        YourMethodCall();
        Assert.IsTrue(true);
    }
    catch {
        Assert.IsTrue(false);
    }
}

Ответ 10

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

Ответ 11

Какой экземпляр вы используете для вызова метода void, вы можете просто использовать Verfiy

Пример:

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

try
{
    this._log.Verify(x => x.LogMessage(Logger.WillisLogLevel.Info, Logger.WillisLogger.Usage, "Created the Student with name as"), "Failure");
}
Catch 
{
    Assert.IsFalse(ex is Moq.MockException);
}

Выбрасывает ли Verify исключение из-за отказа метода, с которым завершился тест?