如何处理单元测试中过多的模拟期望? [英] How can I deal with too Many Mock Expectations in unit tests?

查看:45
本文介绍了如何处理单元测试中过多的模拟期望?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am writing unit tests for my presentation class in MVP pattern.But I am having trouble to write mock setup code.

我有一个演示者,当演示者的 Load 方法被调用时,我想测试视图应该加载类属性、表字段、数据类型、设置演示者......所以当演示者总是加载时我有不同的事情要做添加新的测试期望.而且每次测试都在变大.

I have a presenter and when presenter's Load method called I want to test view should load class properties, table fields, data types,set presenter.... So When I have a different thing to do when presenter load always I have to add new expectation to test. And test is getting bigger every time.

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

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

Is there a code smell in this code? How Can I improve or simplify this?

推荐答案

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

After a long sleepless night and research I have found this solution.When I thougt carefully I have came up with this. I am testing too many behaviour in one test. And I have changed the tests like this

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

我曾经使用过很多 Dynamic mock 来测试一种行为.您也可以阅读 Dave 的一次模拟测试关于这个的文章

I have used lots of Dynamic mock to test one behaviour at time. Also you can read Dave's One Mock Per Test article about this

这篇关于如何处理单元测试中过多的模拟期望?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆