Tired of all that improv show talk? Well, now it’s time for me to get my geek on. Non-computer geeks feel free to tune out. This is actually more along the lines of “put it out there for the sake of future Googlers” than a serious discussion.

I’ve had test-first religion for some time now, but deadlines have made me something of a lapsed tester. After finding a pretty bad-ass bug in my code, I got religion again, admitted I was a sinner, and went forward in Testing. I am redeeming myself by writing a few hundred unit tests of already existing code.

My preferred mock framework is Rhino Mocks. Now I’m all about the AAA (Arrange, Act, Assert) syntax. 99.9% of my tests (seriously, I’ve got over a thousand of them) are AAA. Most of my tests are unordered. I just want to test that something was called, and I don’t care what was called before or after it.

But you can’t do AAA syntax when you’re doing ordered tests. It hasn’t been a problem thus far, but I ran into a problem when I started testing objects that hooked up events in the constructor: So my code looked like this:

[sourcecode language=”c#”]
namespace RhinoMocksOrdredWithEvents {
public interface IOrderedThing {
void FirstThing();
void SecondThing();
void SomethingElse();
event EventHandler OnThingHappened;
}

public class MyTestClass {

private IOrderedThing MyOrderedThing { get; set; }

public MyTestClass(IOrderedThing orderedThing) {
MyOrderedThing = orderedThing;
MyOrderedThing.OnThingHappened += new EventHandler(MyOrderedThing_OnThingHappened);
MyOrderedThing.SomethingElse();
}

public void DoThingsInOrder() {

MyOrderedThing.SomethingElse();

MyOrderedThing.FirstThing();
MyOrderedThing.SecondThing();
}

private void MyOrderedThing_OnThingHappened(object sender, EventArgs e) {
return;
}

}
}
[/sourcecode]

And here’s the test to make sure that FirstThing() and SecondThing() are called in order:

[sourcecode language=”c#”]
namespace RhinoMocksOrdredWithEvents {
[TestClass]
public class OrderedMockTests {

[TestMethod]
public void TestThingsAreRunInOrder() {
// Arrange
MockRepository mocks = new MockRepository();

IOrderedThing mockOrderedThing = mocks.DynamicMock();

MyTestClass classUnderTest = new MyTestClass(mockOrderedThing);

using (mocks.Record()) {
using (mocks.Ordered()) {
mockOrderedThing.Expect(thing => thing.FirstThing());
mockOrderedThing.Expect(thing => thing.SecondThing());
}
}

mockOrderedThing.Replay();

// Act
classUnderTest.DoThingsInOrder();

// Assert
mockOrderedThing.VerifyAllExpectations();
}
}
}
[/sourcecode]

Be not fooled by my spurious use of the //Arange, //Act, and //Assert comments. This is most definitely not the AAA syntax.

So when I tried to run this test, I got the following error:


Test method
RhinoMocksOrdredWithEvents.OrderedMockTests.TestThingsAreRunInOrder
threw exception:
Rhino.Mocks.Exceptions.ExpectationViolationException:
IOrderedThing.add_OnThingHappened(System.EventHandler`1[System.EventArgs]);
Expected #1, Actual #0..

What what what!? I never told Rhino Mocks that I expected the event to be wired! And anyway, it is wired, right there in the constructor, see? Then I comment out the event hookup, and the test works! So off I sauntered to the Rhino Mocks mailing list all like, “Hey guys, I don’t mean to be all smug and stuff, but all y’all got a bug.”

Thankfully, Tim Barcz on the mailing list set me straight.

Yes, Virginia, you can do the AAA syntax in an ordered mock, and this is how you do it:

[sourcecode language=”c#”]
namespace RhinoMocksOrdredWithEvents {
[TestClass]
public class OrderedMockTests {

[TestMethod]
public void TestThingsAreRunInOrder() {
// Arrange
//MockRepository mocks = new MockRepository();

IOrderedThing mockOrderedThing = MockRepository.GenerateMock();

MyTestClass classUnderTest = new MyTestClass(mockOrderedThing);

mockOrderedThing.GetMockRepository().Ordered();

mockOrderedThing.Expect(thing => thing.FirstThing());
mockOrderedThing.Expect(thing => thing.SecondThing());

// Act
classUnderTest.DoThingsInOrder();

// Assert
mockOrderedThing.VerifyAllExpectations();

}
}
}
[/sourcecode]

Which works no matter what strange stuff you want to do in the constructor.

Much thanks to Tim Barcz for setting me straight. Here is the original thread on the Rhino Mocks mailing list.