Модульный тест: проверить, вызывается ли метод - PullRequest
3 голосов
/ 14 октября 2011

У меня есть следующие классы:

public class MyClass
{
    public void MyMethod()
    {
        try
        {
            ...
            save data to file
            ...
        }
        catch (Exception exception)
        { 
            ErrorDisplay.ShowErrorMessage("MyMethod", exception);
        }
    }
}

public class ErrorDisplay
{
    public static ShowErrorMessage(string methodName, Exception exception)
    {
        if (exception is IOException)
            MessageBox.Show(methodName + " : " + GetIODisplayMessage());
        else if ... 
            ...
        else
            ...
   }

    public static string GetIODisplayMessage()
    {
        return "IO error";
    }

    ....
}

Мне нужно написать модульный тест, в котором я буду издеваться над IOException, и мне нужно проверить, что GetIODisplayMessage() метод вызывается. Есть ли способ проверить, вызван ли метод? Или может быть другая идея о том, как сделать модульный тест для моего случая?

Спасибо.

Ответы [ 5 ]

3 голосов
/ 14 октября 2011

Как упомянуто выше, использование статического ErrorDisplay вызывает ряд проблем с тестированием, а внедрение в реализации IErrorDisplay решит некоторые из них, но не все (см. MessageBox ниже).Однако ...

Static + Interface

Если вам нужно сохранить статический класс ErrorDisplay и не хотите использовать Shell для TypeMock, вы можете добавить уровень косвенности

public interface IDisplayErrorImplementation {
    void ShowErrorMessage(string message, Exception ex);
}

public class DefaultDisplayErrorImplementation : IDisplayErrorImplementation {
    public void ShowErrorMessage(string message, Exception ex) {
        //...
    }
}

public static class DisplayError {
    static DisplayError(){
        Implementation = new  DefaultDisplayErrorImplementation();
     }

    public static IDisplayErrorImplementation Implementation { get; set;}

    public static void ShowErrorMessage(string message, Exception ex) {
        Implementation.ShowErrorMessage(message, ex);
    }
}

Вы можете сохранить существующие вызовы ErrorDisplay, но теперь они более заменяемы и тестируемы.

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

MessageBox

У вас есть другая проблема с запуском модульных тестов на ErrorDisplay;у вас появится MessageBox.Не хорошо, если вы пытаетесь запустить тесты в тестовом жгуте (или как часть сборки).

Опять косвенность - твой друг.Вы можете заменить вызов MessageBox.Show () на вызов MessageDisplayService.Show ().Реализация по умолчанию может вызывать окно сообщения, а фиктивное может использоваться для тестирования (либо фиктивная, либо простая реализация ничего не делать)

Юнит тестирование

Каковы границы юнитов для тестирования?

Из вопроса видно, что вы хотите запустить тест для MyClass :: MyMethod (), вызвать IOException и увидеть, что GetIODisplayMessage () вызывается.Если я неправильно понял, пропустите следующий раздел:)

Планируете ли вы делать это для каждого класса / метода, где может возникнуть IOException?Планируете ли вы делать это для каждого класса / метода, где могут возникать все другие типы исключений, обрабатываемые ErrorDisplay?

Это большая работа, для которой просто снова и снова повторяется тестирование кода ErrorDisplay.

Границы, которые я вижу:

MyClass :: MyMethod

Если возникает исключение, оно вызывает ErrorDisplay.ShowErrorMessage (), передавая "MyMethod"и исключение.

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

ErrorDisplay.ShowErrorMessage ()

Если он вызывается с IOException, то он показывает сообщение, которое он получает, вызывая GetIODisplayMessage ().

Это не зависит (как написано выше) от вызывающего кода и может быть проверено модулем отдельно.

ErrorDisplay.GetIODisplayMessage ()

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

При тестировании MyClass :: MyMethod мы хотим убедиться, что при возникновении исключения вызывается код отображения ошибки, передавая правильное имя метода и исключение.

При тестировании ErrorDisplay.ShowErrorMessage (), мы проверяем, что получаем правильное сообщение для типа исключения, который мы вызываем MessageDisplayService.Show () с именем метода + ":" + <> нам не нужно тестировать здесь текст IODisplayMessage.

При тестировании ErrorDisplay.GetIODisplayMessage () мы проверяем, что оно возвращает правильное сообщение.

Надеюсь, это полезно,

Alan.

1 голос
/ 14 октября 2011

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

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

0 голосов
/ 14 октября 2011

Зависит от вашей насмешливой основы. Ни один из бесплатных (Rhino, Moq) не позволяет устанавливать ожидания для статических методов. Вам нужно будет купить коммерческий продукт, такой как Typemock, или еще лучше сделать методы класса ErrorDisplay виртуальными и передать их экземпляр в MyClass.

В качестве примера вы можете затем отправить экземпляр Mock<ErrorDisplay> при использовании Moq и установить ожидание для этого.

0 голосов
/ 14 октября 2011

Вы должны использовать библиотеку насмешек, такую ​​как Moq или Rhino Mocks, посмотрите на это Moq

для статических методов, которые вы можете использовать TypeMock Isolator

но это не бесплатно

0 голосов
/ 14 октября 2011

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

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