Как я могу справиться со слишком большим количеством фиктивных ожиданий в модульных тестах?

Я пишу модульные тесты для своего класса презентации в шаблоне MVP. Но у меня возникают проблемы с написанием фиктивного кода установки.

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

    [Test]
    public void When_Presenter_Loads_View_Should_Display_Selected_Class_Properties()
    {
        IList<string> dataTypes =new List<string>();
        IClassGenerationView view = mockRepository.StrictMock<IClassGenerationView>();
        tableRepository = mockRepository.Stub<ITableRepository>();

        using(mockRepository.Record())
        {
            SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
            view.Presenter = null;
            LastCall.IgnoreArguments();
            view.DataTypes = dataTypes;
            view.Show();

            view.ClassProperties = classProperties;
            view.TableName = "Table";
            view.Table = table;
            LastCall.IgnoreArguments();
        }


        using(mockRepository.Playback())
        {
            ClassGenerationPresenter presenter = new ClassGenerationPresenter(view, clazz,  tableRepository);
            presenter.Load();
        }
    }

Есть ли в этом коде запах кода? Как я могу улучшить или упростить это?


person caltuntas    schedule 01.01.2009    source источник


Ответы (2)


Я боролся с этим годами. Сначала я использовал шаблон MVP, но позже переключился на модель представления (аналог MVVM для WPF/Silverlight). Несмотря на это, результаты никогда не были удовлетворительными, особенно в Agile-проектах, где пользовательский интерфейс быстро меняется. Поэтому мы больше не пишем тесты для этих типов классов и перешли на SpecFlow/WaTiN для создания автоматических тестов пользовательского интерфейса, которые по-прежнему можно поддерживать. Подробнее об этом читайте здесь: http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application

Если вы все еще хотите писать тесты для логики пользовательского интерфейса, я бы определенно не стал использовать метод настройки для удаления некоторых вещей из вашего теста. Очень важно, чтобы вы могли понять причину и следствие теста без необходимости просматривать вверх и вниз. Вместо этого используйте модульный тест в стиле BDD, как я объяснил в этом сообщении блога: http://www.dennisdoomen.net/2010/09/getting-more-out-of-unit-testing.-in.html

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

person Dennis Doomen    schedule 31.01.2012

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

[TestFixture]
public class When_Presenter_Loads
{
    private MockRepository mockRepository;
    private ITableRepository tableRepository;
    private IClass clazz;
    private Dictionary<string, Type> properties;
    private IClassGenerationView view;
    private ClassGenerationPresenter presenter;

    [SetUp]
    public void Setup()
    {
        mockRepository =new MockRepository();
        properties = new Dictionary<string, Type>();

        clazz = mockRepository.DynamicMock<IClass>();
        view = mockRepository.DynamicMock<IClassGenerationView>();
        tableRepository = mockRepository.Stub<ITableRepository>();


    }

    [Test]
    public void View_Should_Display_Class_Properties()
    {
        using(mockRepository.Record())
        {
            SetupResult.For(clazz.Properties).Return(properties);
            view.ClassProperties = properties;
        }

        using(mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Display_Class_Name_As_A_Table_Name()
    {
        using (mockRepository.Record())
        {
            SetupResult.For(clazz.Name).Return("ClassName");
            view.TableName = "ClassName";
        }

        using (mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Display_SQL_Data_Types()
    {
        List<string> dataTypes = new List<string>();

        using(mockRepository.Record())
        {
            SetupResult.For(tableRepository.GetDataTypes()).Return(dataTypes);
            view.DataTypes = dataTypes;
        }

        using(mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }

    [Test]
    public void View_Should_Show_Table()
    {
        using (mockRepository.Record())
        {
            SetupResult.For(clazz.Name).Return("ClassName");
            view.Table = null;
            LastCall.IgnoreArguments();
        }

        using (mockRepository.Playback())
        {
            presenter = new ClassGenerationPresenter(view, clazz, tableRepository);
            presenter.Load();
        }
    }
}

Я использовал много динамических макетов, чтобы проверить одно поведение за раз. Также вы можете прочитать Один макет на тест Дейва. статья об этом

person caltuntas    schedule 02.01.2009
comment
Не могли бы вы отметить этот ответ как правильный? Спасибо! - person guerda; 07.01.2009