Search code examples
c#tddrhino-mocks

How can I deal with too Many Mock Expectations in unit tests?


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

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?


Solution

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

    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