How to Use Rhino Mocks/Debugging Exceptions
ExpectationViolationException
[edit | edit source]The first time I got an ExpectationViolationException , I was baffled. Here's what it looked like:
failed: Rhino.Mocks.Exceptions.ExpectationViolationException : IInternalSearchService.ProcessIndexingRequest(collaboration.thecompany.com.internalServiceContractsObjects._2007._12.AuthenticationCredentials, "Zardoz", \[collaboration.thecompany.com.internalSearch._2007._12.IndexingWork\]); Expected #0, Actual #1. IInternalSearchService.ProcessIndexingRequest(collaboration.thecompany.com.internalServiceContractsObjects._2007._12.AuthenticationCredentials, "Zardoz", \[collaboration.thecompany.com.internalSearch._2007._12.IndexingWork\]); Expected #1, Actual #0. |
Cryptic, and ultimately not very helpful (at least to me). Basically, all you know when seeing this is that something went wrong with an expectation you set up in your test. Here are a few more things to know, and things you can do to try and debug these kinds of problems:
- Expectations have to do with both the expected calls _and_ the expected parameters. If, in your test, you say something like, Expect.Call(myMock.DoSomething(fooObject)), Rhino.Mocks expects that myMock.DoSomething will be called with _the exact instance_ of fooObject.
- When Rhino.Mocks compares expected parameters (like fooObject in the previous point), it uses the object's Equals() method. This means that even if your expected object has all the same property values, etc., comparison will fail unless you are able to pass the _exact_ expected instance (or unless you override Equals(), which is generally a not-so-great idea). In 3.4, Rhino.Mocks introduced the Property.AllPropertiesMatch() constraint which does a reflective property comparison for objects, e.g.,
Expect.Call(myMock.DoSomething(fooObject)).IgnoreArguments().Constraints(Property.AllPropertiesMatch(fooObject)); |
- I.e., expect a call to myMock.DoSomething, "ignoring" all passed arguments, but constrained by the following: that the first arguments properties match fooObject's properites exactly.
- You can add a Rhino.Mocks logger to print data to the console. This can give a bit more detail on what's happening where and why. Just add the following line to your test, before the mocking work:
RhinoMocks.Logger = new TextWriterExpectationLogger(Console.Out); |
- When Rhino.Mocks compares two objects during expectation validation, and something goes wrong, the data you get in the exception message comes from the ToString() on the objects. So, you can override ToString() in the class of the objects which are being compared; override it to give you some info about what might be going wrong with the comparison (like, override it to spit out the various properties on the objects).