CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

Generic constraint for Rhino Mocks - make unit tests more readable

I use Rhino Mocks, and I encourage you to do the same.  When unit testing, sometimes its necessary to interrogate an object that was passed to a dependency.

Consider the following test code:

   1:  [Test]
   2:  public void ShouldSaveObjectWithAllInformation()
   3:  {
   4:      string firstName = "Jeffrey";
   5:      string lastName = "Palermo";
   6:   
   7:      MockRepository mocks = new MockRepository();
   8:      IPersonRepository personRepository = (IPersonRepository) mocks.CreateMock(typeof (IPersonRepository));
   9:   
  10:      personRepository.SavePerson(null);
  11:      GenericConstraint personConstraint = new GenericConstraint();
  12:      LastCall.On(personRepository).Constraints(personConstraint);
  13:   
  14:      mocks.ReplayAll();
  15:   
  16:      PersonController controller = new PersonController(personRepository);
  17:      controller.PersonFirstName = "Jeffrey";
  18:      controller.PersonLastName = "Palermo";
  19:      controller.Save();
  20:   
  21:      mocks.VerifyAll();
  22:   
  23:      Person person = (Person) personConstraint.GetParameterObject();
  24:      Assert.That(person.FirstName, Is.EqualTo(firstName));
  25:      Assert.That(person.LastName, Is.EqualTo(lastName));
  26:  }
 

This is a case where we have a class that takes information, creates an object and sends it to a dependency. The dependency doesn't need to return what was just passed to it, but in our unit test, we need to be able to assert that the object was created correctly before being passed to the dependency.  This is not an edge case.  I run into this scenario quite often.

What did I do to keep my test readable?  I created a Rhino Mocks constraint class that captures the argument passed to a dependency.  Later, I can write plain old asserts that verify the state of the object.   Here is the class:

   1:  public class GenericConstraint : AbstractConstraint
   2:  {
   3:      object _theObject;
   4:   
   5:      public override bool Eval(object obj)
   6:      {
   7:          _theObject = obj;
   8:          return true;
   9:      }
  10:   
  11:      public object GetParameterObject()
  12:      {
  13:          return _theObject;
  14:      }
  15:   
  16:      public override string Message
  17:      {
  18:          get { return ""; }
  19:      }
  20:  }

I prefer this over even the built-in constraints Rhino Mocks provides because I find the Assert syntax to be more familiar with more programmers than the in-line constraint syntax.  Notice on line 12 of the test listing that I'm assigning this constraint to the mocked call to IPersonRepository.  This allows me to come back later on line 23 and pull the object for interrogation.  Once I have a reference to the object that was passed to my dependency, I can write the appropriate asserts.

Feel free to use this constraint class or comment with how you've handled this situation.



Comments

Garry Shutler said:

Very interesting! I'll be trying this out soon. I agree that the assertions contained in your expectations can be quite hidden at times and this looks like a good way of dragging those out.

As an aside, have you seen the generic syntax for MockRepository.CreateMock? I find it makes my mock object creation look much nicer:

IPersonRepository personRepository = mocks.CreateMock<IPersonRepository>();

Excuse anything lost in the VB to C# translation.

# October 2, 2007 9:21 AM

Jeffrey Palermo said:

@Garry,

Yes, I do use the Generic syntax.  I happened to be working in a VS2003 project when I whipped up this sample code.

# October 2, 2007 10:07 AM

Joe said:

What test framework uses "Assert.That"?

ps and I hate to ask and seem nit-picky, but do you think you could turn line numbers off when you post code?   I understand that it has its aesthetic advantages, but to simpletons like myself who have to cut and paste and try everything out in the IDE to see how it really works, they're a pain.

# October 2, 2007 10:53 AM

Shane Courtrille said:

Awesome example.  This is much easier then doing a Do() to test the parameters.

# October 2, 2007 2:11 PM

ScottBellware said:

I don't get the test.  Looks like interesting re-use, and it's certainly "readable", but I'm not getting it on first through fifth glance.  If you have time at some point, I'd like to dissect it.

# October 2, 2007 2:18 PM

Joe Ocampo said:

@Joe

That is the new behavioral constraint assertion model of NUnit 2.4

www.lostechies.com/.../nunit-s-new-constraint-model.aspx

# October 2, 2007 4:06 PM

Garry Shutler said:

It took me a few reads to get it but (please correct me if I'm wrong):

A constraint is checked  by passing the parameters fed to the method to the Eval function as an object. Jeff's object stores this parameter for later use and returns true (as if the constraint was satisfied). This means we have a copy of what was passed to the method and we use the GetParameterObject function to later retrieve the object so we can test its contents against our expectations.

One question that this has raised for myself is how this works for multi-parameter methods, is the parameter object an array of objects which we need to cast individually? This would make sense to me but I haven't had chance to try it out.

# October 2, 2007 5:11 PM

Jeffrey Palermo said:

@Garry,

Your description is correct.

If the dependency required 3 arguments, then you would create 3 instances of GenericConstraint, and each one would receive a method argument.  If the method has 7 arguments, you have to provide 7 GenericConstraint instances, and you can name each one appropriately so it will be easy to retrieve the parameter objects one at a time.

# October 2, 2007 5:25 PM

Martin Jul said:

I favour implementing Equals on the parameter object over using the constraints.

This way I get very simple code like

Person expectedPerson = new Person(firstName, lastName);

personRepository.SavePerson(expectedPerson);

LastCall.On(personRepository);

// ...

mockRepository.VerifyAll();

The Asserts are that in a way they circumvent the object-orientation by asserting state outside of the object itself - and they make for bulky test-code that needs to change in synch with changes to the Person class.

Using Equals this reduces to a matter of constructing the expected object (standard constructor) and using its built-in Equality method.

# October 3, 2007 7:29 AM

Jeffrey Palermo said:

@Martin,

I, too, favor overriding the Equals(obj) method, and encourage that whenever possible (and over the technique described here).

In cases where that won't work or is insufficient, the above is the best I'm come up with in .Net 1.1

Note, in .Net 2.0 and the latest release of Rhino Mocks, the "Do( )" method can be used with an anonymous delegate to hold the NUnit asserts.

# October 3, 2007 8:32 AM

Robert Ensor said:

You stole my idea! ;) Now maybe you can steal an idea off me that i haven't thought of yet:

What happens when your test expects that SavePerson be called twice, with completely different parameters? Rhino can handle this (ordered or unordered) for cases where the pbject properties are "unrolled" into the method args, but if you want to test data objects, you're in trouble (or should i say, i'm in trouble)

What I ended up doing is creating another contstraint that stores EACH argument into a list, and then checking the contents of that list. But that seems very far from the original intent of rhino :(

What do you think?

@Martin: I prefer that too but in some cases i have a property on my object that is meant to be set to an autonumber or the current date (something out of my control), so i want to ignore that property *for just this test*

# October 5, 2007 12:38 AM

saret said:

Lol, me too, been playing with a similar idea recently

I also tend to use the Equals(obj) method, however sometimes (such as in my newest project using Boo) I've tended to also use a different technique that can be done in c# 2, but really doesn't look really nearly as clean compared to Boo's closures (or the new lambda expressions in c# 3).

This way also allows you to just optionally test certain values of the expected object passed which handles Robert's autonumber issue.

(upgraded to generics - but not the record/playback layout)

________________________________________________

using Rhino.Mocks;

using Rhino.Mocks.Constraints;

string firstName = "Jeffrey";

string lastName = "Palermo";

Predicate<Person> constraint = new Predicate<Account>(delegate(Person p)

{

return p.FirstName == firstName && p.LastName == lastName ;

});

MockRepository mocks = new MockRepository();

IPersonRepository personRepository = mocks.CreateMock<IPersonRepository>();

personRepository.SavePerson(null);

GenericConstraint personConstraint = new GenericConstraint();

LastCall.On(personRepository).Constraints(Is.Matching<Person>(constraint));

mocks.ReplayAll();

PersonController controller = new PersonController(personRepository);

controller.PersonFirstName = firstName;

controller.PersonLastName = lastName;

controller.Save();

mocks.VerifyAll();

_____________________________________

Haven't really gotten into blogging yet (not like I've tried hard ... got like 15 drafts and one published rant), but was wierdly enough already writing a post on this technique a day or two ago before I saw this, which including some ways that I've used to handle the multiple calls Robert is mentioning.

I'm gonna still blog a bit about this technique (this one I'm am actually gonna publish! <shmuck avoidance incentive by stating this -  I better actually post this weekend>) and "extensions" to it I've used such as currying ala:

(note it's in boo I'll post c# version as well)

[Test]

def sometest():

invalidReason = "my reason"

constraint = def(player as Player) as Predicate[of InvalidMoveEventArgs]:

return {e as InvalidMoveEventArgs | e.Player == player & e.Reason = invalidReason}

/......./

This technique is ideally suited to ordered, but the regular straight closure route could be used in unordered (by keeping some state as to which one of the expected values has/hasn't been passed yet in the enclosing method/data holder...)

# October 5, 2007 8:07 PM

saret said:

sorry hit post button just before i finished off,

(if my post can be fixed much appreciated :) )

the c# example should read:

string firstName = "Jeffrey";

string lastName = "Palermo";

Predicate<Person> constraint = new Predicate<Account>(delegate(Person p)

{

  return p.FirstName == firstName && p.LastName == lastName ;

});

MockRepository mocks = new MockRepository();

IPersonRepository personRepository = mocks.CreateMock<IPersonRepository>();

personRepository.SavePerson(null);

LastCall.On(personRepository).Constraints(Is.Matching<Person>(constraint));

mocks.ReplayAll();

PersonController controller = new PersonController(personRepository);

controller.PersonFirstName = firstName;

controller.PersonLastName = lastName;

controller.Save();

mocks.VerifyAll();

# October 5, 2007 8:19 PM

saret said:

And that is why commenting about stuff and using a text editor to scrap up code after 2 am is a bad idea (Predicate<Account> should be Predicate<Person>)

sorry folks

# October 5, 2007 8:35 PM

Unit Testing object parameters using Rhino Mock Constraints « Justin Saret’s incongruous thoughts said:

Pingback from  Unit Testing object parameters using Rhino Mock Constraints &laquo; Justin Saret&#8217;s incongruous thoughts

# October 6, 2007 1:16 PM

Martin Jul said:

@Robert:

Regarding Equals or constraints you wrote

"@Martin: I prefer that too but in some cases i have a property on my object that is meant to be set to an autonumber or the current date (something out of my control), so i want to ignore that property *for just this test*

"

In cases like this I would factor out the magic into an "IMagicProvider" - for example, a class that can provide the current time. This way you have control over your environment in the test - just use, say, a mock or a stub that provides a fixed timestamp, and you will be able to use Equals.

I prefer this static approach to having to deal with dynamic magic in my tests.

# October 8, 2007 4:33 AM

Aaron Feng said:

Another reason for Rhino Mocks Generic Constraint...

aaronfeng.com/.../another-reason-for-rhino-mocks-generic-constraint

# October 8, 2007 7:26 AM

jsmith said:

Thank you!!

# November 21, 2007 6:02 PM

Steven Harman said:

I know the .Do() method will work, but I've found that sometimes it's a bit more verbose and less obvious than the GenericConstraints way of doing it. So I've added a genericised version of the class:

public class Constraint<T> : AbstractConstraint where T : class

{

   T _theObject;

   public override bool Eval(object obj)

   {

       _theObject = obj as T;

       return _theObject != null;

   }

   public T GetParameterObject()

   {

       return _theObject;

   }

   public override string Message

   {

       get { return ""; }

   }

}

Which works well and saves that fugly cast. :)

# March 3, 2008 11:25 AM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication