Окно сообщений и модульное тестирование - PullRequest
8 голосов
/ 19 декабря 2011

Я пытаюсь найти лучший способ отсоединить почтовые ящики от моей логики, чтобы я мог правильно протестировать его.Теперь мне было интересно, будет ли этого достаточно, если я просто создаю отдельный вспомогательный класс (C #), который я позже смогу заглушить для своего сообщения.Например:

static class messageBoxHelper
{
    public static void msgBoxAlg(string message, string title, MessageBoxButtons   buttons, MessageBoxIcon icons, bool show)
    {
        if (show)
        {
            MessageBox.Show(message, title, buttons, icons);
        }
 }

Тогда каждый раз, когда мне нужно было использовать ящик сообщений, я просто использовал messageboxHelper / msgBoxAlg (...) вместо messagebox.show (...).Используя bool show, я мог включить или отключить его во время тестирования.

Мне просто интересно, является ли это "правильным способом".Я имею в виду, есть ли более простой или лучший способ сделать это правильно?Я не могу просто угробить ящики сообщений, они передают «жизненно важную» информацию пользователю («Хотите закрыть эти окна?» ДА / НЕТ и т. Д.).Может также быть, что я не использую правильную программную инженерию, и я должен отделить свои почтовые ящики от моей бизнес-логики?

Ответы [ 4 ]

31 голосов
/ 19 декабря 2011

Да, это правильный путь.Но вместо статического класса вы должны реализовать IDialogService и внедрить его в классы, которые должны отображать диалоги:

public interface IDialogService
{
    void ShowMessageBox(...);

    ...
}

public class SomeClass
{
    private IDialogService dialogService;

    public SomeClass(IDialogService dialogService)
    {
       this.dialogService = dialogService;
    }

    public void SomeLogic()
    {
        ...
        if (ok)
        {
            this.dialogService.ShowMessageBox("SUCCESS", ...);
        }
        else
        {
            this.dialogService.ShowMessageBox("SHIT HAPPENS...", ...);
        }
    }
}

Во время тестирования SomeClass вы должны внедрить фиктивный объект IDialogService вместо реальногоone.

Если вам нужно проверить больше логики пользовательского интерфейса, попробуйте использовать шаблон MVVM .

2 голосов
/ 19 декабря 2011

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

посмотрите на http://martinfowler.com/articles/injection.html для деталей по IoC, мой любимый контейнер - Ninject (http://ninject.org)

1 голос
/ 25 февраля 2014

«Юнит тест», в его точном значении, является тестом атомного поведения. Это не единственный вид тестов на основе кода, которые вы можете сделать для своего кода. Специально для тестирования более длинных сценариев с упомянутыми выше диалоговыми окнами «Да / Нет» более масштабные тесты на основе кода часто более эффективны, чем модульные тесты.

Однако, чтобы их было проще писать, было бы хорошо не только создать специальный сервис, как упомянул Сергей, но и сделать его вызовы асинхронными:

public interface IDialogService
{
    Task<bool> ShowYesNoMessageBox(...);
    ...
}

Оборачивая почтовые ящики в не асинхронные вызовы служб и насмехаясь над ними, для более длинных сценариев вы начнете противоречить шаблону "Arrange-Act-Assert", прогнозируя действия пользователя до того, как это произойдет (выполнение "Arrange" вместо "Act" "), что может вызвать многочисленные проблемы при тестировании, особенно если ваши тесты выполняются с использованием BDD / SpecFlow. Выполнение этих вызовов асинхронно позволяет избежать таких проблем. См. Мою статью блога для получения подробной информации и примеров более масштабных тестов с ящиками сообщений.

1 голос
/ 19 декабря 2011

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

Судя по вашему вопросу, я бы предположил, что ваш код на самом деле не должен использовать MessageBox. Возможно, вместо этого рассмотрите возможность использования обратного вызова или произвольного Action, или подходов, упомянутых Люком МакГрегором и Сергеем В.

...