Search code examples
c#rhino-mocks

RhinoMock - Multiple Expectations in one method - Best Practice


I would like to know how you guys handle something like this. Whats the best practice..

Lest say I have a Method called Load on a presenter object

at first the method looks like this :

public void Load(ViewMode mode, int? id)
{
     if(mode == ViewMode.Modify)
          view.CurrentEntity = model.GetMyEntityById(id.GetValueOrDefault(0));
     else
          view.CurrentEntity = model.CreateNewEntity();
}

To test this code I have 2 tests using RhinoMock to setup expectations

[TestMethod]
public void Load_ShouldCallModelToGetEntityIfViewModeEqualsModify()
{
     IView view = _mockery.StrictMock<IView>();
     IModel model = _mockery.StrictMock<IModel>();

     Entity e = new Entity()

     using(_mockery.Ordered())
     {
          Expec.Call(model.GetMyEntityById(3)).Return(e)
          view.CurrentEntity = e;
     }
     _mockery.ReplayAll()

    Presenter sut = new Presenter(view, model);

    sut.Load(ViewMode.Modify, 3);

    _mockery.VerifyAll();
}

And I then I have another test that test the other path for the ViewMode.Add...

So my question is if I changed the Load method on the presenter to looks like

public void Load(ViewMode mode, int? id)
{

     view.CollectionA = model.GetListOfA();  <------ADDED THIS 
     view.CollectionB = model.GetListOfB();  <------AND THIS

     if(mode == ViewMode.Modify)
          view.CurrentEntity = model.GetMyEntityById(id.GetValueOrDefault(0));
     else
          view.CurrentEntity = model.CreateNewEntity();
}

now I have to add the expectation for both GetList methods in all my previous test or it will result in Expected 0 Actual 1. Also I will have to change my test name because in the test I expect far more than just calling the model to get an entity by its id.

So is there a best pratice for that. Is changing all my tests is the correct way to do things when I add call to some mocks, or there is a way to expect just some calls for previous test and add another test that would be something like : [TestMethod] public void Load_ShouldCallModelToObtainAListOfA();

and it would not make my other tests to fail.

I know its a vague question but if somebody understand what I ask please tell me how you handle this kind of situation with behavior tests.

Thank you very much Breach


Solution

  • It looks like you're writing your unit tests to make sure certain methods are called to achieve the results you want. Don't do this. It makes your tests very brittle and makes refactoring difficult.

    Instead, just test the behavior of your Load method, not how that behavior is implemented. From looking at your Load method, it's populating a couple of collections and setting the CurrentEntity property. So your test should simply make sure that after the Load method was called, the collections are set and that the CurrentEntity is set to the one you expect.

    Stub out the model to return some canned responses for the various methods called on the model object and then run your test. Verify that the canned values come back in your view.