1

我正在用 MVP 模式为我的演示类编写单元测试。但是我在编写模拟设置代码时遇到了麻烦。

我有一个演示者,当调用演示者的 Load 方法时,我想测试视图应该加载类属性、表字段、数据类型、设置演示者......所以当演示者加载时我有不同的事情要做时,我必须添加新的期待测试。并且测试每次都变得越来越大。

    [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();
        }
    }

这段代码中是否有代码异味?我该如何改进或简化这一点?

4

2 回答 2

2

多年来我一直在为此苦苦挣扎。起初我使用 MVP 模式,但后来切换到 Presentation Model(类似于 WPF/Silverlight 的 MVVM)。无论如何,结果从来都不是令人满意的,尤其是在 UI 快速变化的敏捷项目中。因此,我们不再为这些类型的类编写测试,而是切换到 SpecFlow/WaTiN 来创建仍然可维护的自动化 UI 测试。在此处阅读更多信息:http: //www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application

如果您仍想为 UI 逻辑编写测试,我绝对不会使用 setup 方法从测试中删除一些内容。您必须能够理解测试的原因和影响,而无需上下浏览。相反,使用更 BDD 风格的单元测试,就像我在这篇博文中解释的那样:http: //www.dennisdoomen.net/2010/09/getting-more-out-of-unit-testing-in.html

一般来说,我将这些 BDD 风格的测试用于本质上非常管控的类,而对普通类使用更多的 AAA 风格的测试。

于 2012-01-31T19:41:11.207 回答
1

经过漫长的不眠之夜和研究,我找到了这个解决方案。当我仔细考虑时,我想出了这个。我在一项测试中测试了太多的行为。我已经改变了这样的测试

[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();
        }
    }
}

我曾经使用过很多动态模拟来测试一种行为。您也可以阅读 Dave 的One Mock Per Test文章关于此

于 2009-01-02T13:00:47.060 回答