Wiring Event in Constructor With Ordered Mock: Bug, or am I Doing it Wrong?

10 views
Skip to first unread message

Jason Specland

unread,
Sep 13, 2010, 10:47:33 AM9/13/10
to Rhino.Mocks
Hey there,

I'm having an problem when I try to wire up an event in one of my
classes inside the constructor whenever the "event" is part of my mock
object, and the tests I'm running are ordered. It's easier to show
than to explain, so here's some sample code:

My sample class under test:

namespace RhinoMocksOrdredWithEvents {

public interface IOrderedThing {
void FirstThing();
void SecondThing();
void SomethingElse();
event EventHandler<EventArgs> OnThingHappened;
}

public class MyTestClass {

private IOrderedThing MyOrderedThing { get; set; }

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

public void DoThingsInOrder() {

MyOrderedThing.SomethingElse();

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

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

}
}


And my sample test:

namespace RhinoMocksOrdredWithEvents {
[TestClass]
public class OrderedMockTests {

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

IOrderedThing mockOrderedThing =
mocks.DynamicMock<IOrderedThing>();

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();

}
}
}

When I run the tests, I get 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..

Which is odd, since not only did I never say I expected the event to
be added, but the event was, in fact, added.

If I comment out the event wiring, the test passes. If I wire the
event in the method rather than in the constructor, the test passes.

It seems like a bug to me, but I'm very hesitant to call it such when
it is far more likely to be the result of my own ignorance. So what
am I missing?

-- Jason

Tim Barcz

unread,
Sep 13, 2010, 2:45:26 PM9/13/10
to rhino...@googlegroups.com
Jason,

The problem doesn't exist with the event at all, the problem is with the larger test, using the record/replay semantics.  What's happening is that behind the scenes is that there are a total of four expectations being set - the constructor sets two (one on OnThingHappened and one on SomethingElse()).  The other two expectations are set explicitly by you when you call mockOrderedThing.Expect...twice for FirstThing() and SecondThing().  Once in replay mode, you call DoThingsInOrder which calls SomethingElse(), FirstThing(), SecondThing(), thus satisfying three of the four expectations. The only unsatisfied expectation is the event - which as you've found is never called.

Commenting out the call in the constructor removes the expectation - which is why it passes.

To further illustrate that it's not the event, comment out the call in to SomethingElse() in DoThingsInOrder(), you'll find the test fails.

What's really going on here is a problem with record/replay.  Anything that is called in record play is expected to be called later on, which the event is never triggered.  To get what you're going for I would suggest changing the code to AAA syntax (a good suggestion in general) to the following:

[TestMethod]
public void TestThingsAreRunInOrderAAA()
{
// Arrange
IOrderedThing mockOrderedThing = MockRepository.GenerateMock<IOrderedThing>();
MyTestClass classUnderTest = new MyTestClass(mockOrderedThing);

// Act
classUnderTest.DoThingsInOrder();

// Assert
mockOrderedThing.AssertWasCalled(thing => thing.FirstThing());
mockOrderedThing.AssertWasCalled(thing => thing.SecondThing());
}


--
You received this message because you are subscribed to the Google Groups "Rhino.Mocks" group.
To post to this group, send email to rhino...@googlegroups.com.
To unsubscribe from this group, send email to rhinomocks+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/rhinomocks?hl=en.




--
Tim Barcz
Microsoft C# MVP
Microsoft ASPInsider
http://timbarcz.devlicio.us
http://www.twitter.com/timbarcz

Tim Barcz

unread,
Sep 13, 2010, 2:46:01 PM9/13/10
to rhino...@googlegroups.com
By the way...let me know if this explains it or if you (or anyone) need anymore assistance, I'd be glad to help.

Tim Barcz

unread,
Sep 13, 2010, 2:52:40 PM9/13/10
to rhino...@googlegroups.com
Also, please note that my example is not ordered.  To make my example worked for ordered semantic see the following (note the moving of the expectation setting - which would also work for the previous example) and the line mockOrderedThing.GetMockRepository().Ordered() which changes the underlying recorder from unordered to ordered:


[TestMethod]
public void TestThingsAreRunInOrderAAA()
{
// Arrange
IOrderedThing mockOrderedThing = MockRepository.GenerateMock<IOrderedThing>();
MyTestClass classUnderTest = new MyTestClass(mockOrderedThing);
mockOrderedThing.GetMockRepository().Ordered();

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

// Act
classUnderTest.DoThingsInOrder();

mockOrderedThing.VerifyAllExpectations();

Jason Specland

unread,
Sep 16, 2010, 11:49:23 AM9/16/10
to Rhino.Mocks
Ah, I see now! Thank you so much.

I understand that using the AAA syntax is considered superior... I've
done it for 99.9% of my tests. I just wasn't aware that there was an
AAA (more or less) way to do ordered mocks.

Thanks again for your assistance.

-- Jason

On Sep 13, 2:52 pm, Tim Barcz <timba...@gmail.com> wrote:
> Also, please note that my example is not ordered.  To make my example worked
> for ordered semantic see the following (note the moving of the expectation
> setting - which would also work for the previous example) and the line *
> mockOrderedThing.GetMockRepository().Ordered()* which changes the underlying
> recorder from unordered to ordered:
>
> [TestMethod]
> public void TestThingsAreRunInOrderAAA()
> {
> // Arrange
> IOrderedThing mockOrderedThing =
> MockRepository.GenerateMock<IOrderedThing>();
> MyTestClass classUnderTest = new MyTestClass(mockOrderedThing);
> mockOrderedThing.GetMockRepository().Ordered();
>
> mockOrderedThing.Expect(thing => thing.FirstThing());
> mockOrderedThing.Expect(thing => thing.SecondThing());
>
> // Act
> classUnderTest.DoThingsInOrder();
>
> mockOrderedThing.VerifyAllExpectations();
>
>
>
>
>
> }
> On Mon, Sep 13, 2010 at 1:46 PM, Tim Barcz <timba...@gmail.com> wrote:
> > By the way...let me know if this explains it or if you (or anyone) need
> > anymore assistance, I'd be glad to help.
>
> >>> rhinomocks+...@googlegroups.com<rhinomocks%2Bunsubscribe@googlegrou­ps.com>
> >>> .
> >>> For more options, visit this group at
> >>>http://groups.google.com/group/rhinomocks?hl=en.
>
> >> --
> >> Tim Barcz
> >> Microsoft C# MVP
> >> Microsoft ASPInsider
> >>http://timbarcz.devlicio.us
> >>http://www.twitter.com/timbarcz
>
> > --
> > Tim Barcz
> > Microsoft C# MVP
> > Microsoft ASPInsider
> >http://timbarcz.devlicio.us
> >http://www.twitter.com/timbarcz
>
> --
> Tim Barcz
> Microsoft C# MVP
> Microsoft ASPInsiderhttp://timbarcz.devlicio.ushttp://www.twitter.com/timbarcz- Hide quoted text -
>
> - Show quoted text -
Reply all
Reply to author
Forward
0 new messages