How can I do too many Mock Expectations in unit tests?

I am writing unit tests for my presentation class in MVP pattern. But I find it hard to write mock setup code.

I have a presenter, and when I call the Presenter Load method that I want to check, it has to load class properties, table fields, datatypes, set a presenter .... So when I have to do something else to add a new expectation for testing. And the test is getting bigger and bigger.

    [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?

+1


source to share


2 answers


After a long sleepless night and researching, I found this solution. When I carefully came up with this. I am testing too many behaviors in one test. And I changed 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();
        }
    }
}

      



I have used many dynamic layouts to test one behavior at a time. Also you can read Dave One Mock Per Test about this

+1


source


I've struggled with this for years. I used the MVP pattern at first, but later switched to the view model (similar to MVVM for WPF / Silverlight). Despite this, the results have never been satisfactory, especially in Agile projects where the user interface changes rapidly. Therefore, we no longer write tests for these class types and switched to SpecFlow / WaTiN to create automated UI tests that are still supported. Read more about this here: http://www.codeproject.com/Articles/82891/BDD-using-SpecFlow-on-ASP-NET-MVC-Application

If you still want to write tests for UI logic, I would definitely not use the install method to remove some of the stuff from your test. It is very important that you can understand the cause and effect of the test without having to look up and down. Use a more BDD type unit test style instead, as I explained in this blog post: http://www.dennisdoomen.net/2010/09/getting-more-out-of-unit-testing-in.html



In general, I use these BDD style tests for classes that are very orchastrational in nature, and more AAA tests for regular classes.

+2


source







All Articles