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:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
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.