Recently, Ayende Rahien (Oren Eini) blogged about Planning for Rhino Mocks 4.0.  He’s calling for all of us to contribute our ideas on how to improve Rhino Mocks.  He set up a forum where we can submit our ideas and vote on them as well.

This lead me to review some of my more complex tests involving Rhino Mocks (I’m on version 3.6).  Were there mocking difficulties that I could propose a solution to?  Let’s find out…

A frequent pattern in my tests is verifying that my controllers pull properties from the views correctly.  The controller would construct a new entity object, providing the values from various view properties.  The entity object then would be passed to the data provider to save the entity.

The first attempt to test that a particular property was passed through correctly went something like this:

   1: _model.AssertWasCalled( m => m.Add<Job>( null ),
   2:                         o => o.Constraints(
   3:                                  Is.Matching<Job>( j => j.Account.Id == _accountId ) ) );

Fairly straight forward, but the failure message doesn’t provide much information:

   1: failed: Rhino.Mocks.Exceptions.ExpectationViolationException : IMyModel.Add<Job>(Predicate (TestClass.<Test>b__12(obj);)); Expected #1, Actual #0.

Marginally better is the use of the Arg helper class:

   1: var arg = Arg<Job>.Matches( j => j.Account.Id == _accountId );
   2: _model.AssertWasCalled( m => m.Add<Job>( arg ) );

…with this failure message:

   1: failed: Rhino.Mocks.Exceptions.ExpectationViolationException : IMyModel.Add<Job>(j => (j.Account.Id = (value(TestClass)._accountId ))); Expected #1, Actual #0.

This gave me a better idea as to the check that was failing (honestly that is what my test method name is for), but without helpful details.

So I changed the original approach slightly by adding an assertion within the constraint delegate, like so:

   1: _model.AssertWasCalled( m => m.Add<Job>( null ),
   2:                         o => o.Constraints(
   3:                                  Is.Matching<Job>( j =>
   4:                                      {
   5:                                          j.Account.Id.ShouldEqual( _accountId );
   6:                                          return true;
   7:                                      } ) ) );

Now I am using an explicit “ShouldEqual”, and I get:

   1: failed: 
   2:   Expected: 143
   3:   But was:  142

But, that “return true” is just ugly, and there’s a lot going on just to test that the account id was passed through correctly.

Then I discovered the Rhino Mock extension method GetArgumentsForCallsMadeOn:

   1: var arg = (Job)(_model.GetArgumentsForCallsMadeOn( m => m.Add<Job>( null ) )[0][0]);
   2: arg.Account.Id.ShouldEqual( _accountId );

After all, I didn’t really want to assert that the Add method was called.  I wanted to assert that the method was called with the correct parameters, but, with each parameter under a different test:

   1: [Specification]
   2: public void the_job_should_be_add_to_the_queue()
   3: {
   4:     _model.AssertWasCalled( m => m.Add<Job>( Arg<Job>.Is.Anything ) );
   5: }
   6:  
   7: [Specification]
   8: public void the_selected_account_id_should_be_used()
   9: {
  10:     var jobArg = (Job)(_model.GetArgumentsForCallsMadeOn( m => m.Add<Job>( null ) )[0][0]);
  11:     jobArg.Account.Id.ShouldEqual( _accountId );
  12: }
  13:  
  14: [Specification]
  15: public void the_selected_from_date_should_be_used()
  16: {
  17:     var jobArg = (Job)(_model.GetArgumentsForCallsMadeOn( m => m.Add<Job>( null ) )[0][0]);
  18:     jobArg.FromDate.ShouldEqual( _fromDate );
  19: }
  20:  
  21: [Specification]
  22: public void the_selected_to_date_should_be_used()
  23: {
  24:     var jobArg = (Job)(_model.GetArgumentsForCallsMadeOn( m => m.Add<Job>( null ) )[0][0]);
  25:     jobArg.ToDate.ShouldEqual( _toDate );
  26: }
  27:  
  28: [Specification]
  29: public void the_selected_line_items_should_be_used()
  30: {
  31:     var jobArg = (Job)(_model.GetArgumentsForCallsMadeOn( m => m.Add<Job>( null ) )[0][0]);
  32:     jobArg.LineItems.Select( li => li.LineItem.Id ).ShouldHaveSameElements( _lineItems );
  33: }

That’s good enough for me.  I guess I will have to search for some other ideas to improve Rhino Mocks.