Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,592
|
Comments: 51,225
Privacy Policy · Terms
filter by tags archive

Murphy's Revenge

time to read 1 min | 184 words

I was just preparing a big surprise to celebrate the release of Rhino Mocks 3.0 (expected very soon), when I run into a critical bug in the handling of non generic types inheriting from generic types, basically:

public interface IUserRepository : IRepository<User, string> {} 

The above can't be mocked. And nothing caught it until I was doing some "let us show the new stuff" preparations. As an aside, 85% of the bugs in Rhino Mocks at the moment can be traced directly to generics support. (10% are related to custom attributes support and another 5% is new features that aren't playing well with the rest of the system).

Generics look so nice on the surface, until you get deep into them. I have found a whole new world of appreciation to the compiler teams and the CLR to build such a leaks-proof abstraction over the required complexity.

time to read 1 min | 121 words

I am starting to see a lot more refernces to Rhino Mocks in blogs and articles, which is really great. What is interesting is that I get to see a lot of mocking related code (either on the Rhino Mocks list or directly). People are doing some crazy stuff with Rhino Mocks, things I never imagined that they would do.

What is the strangest thing that you ever used a mock object for?

For myself, I used it to implement an in memory database based on expectations matching the results to a query. (And if you can't figure that out, I am glad, talk about trying to grok that.)

time to read 12 min | 2323 words

From the WatiN mailing list, using Rhino Mocks to verify that exceptions originating from IE won't fail the test:

[Test]

public void ExceptionsInDialogHandlersShouldBeLoggedAndNeglected()

{

   MockRepository mocks = new MockRepository();

 

   ILogWriter mockLogWriter = (ILogWriter) mocks.CreateMock(typeof (ILogWriter));

   IDialogHandler throwExceptionDialogHandler = (IDialogHandler) mocks.CreateMock(typeof (IDialogHandler));

   IDialogHandler simpleDialogHandler = (IDialogHandler) mocks.CreateMock(typeof (IDialogHandler));

   Window dialog = (Window) mocks.DynamicMock(typeof (Window), IntPtr.Zero);

 

   Expect.Call(dialog.IsDialog()).Return(true);

   Expect.Call(dialog.Visible).Return(true);

   Expect.Call(throwExceptionDialogHandler.HandleDialog(dialog)).Throw(new Exception());

   mockLogWriter.LogAction("");

   LastCall.Constraints(Text.Like("Exception was thrown while DialogWatcher called HandleDialog:"));

   mockLogWriter.LogAction("");

   LastCall.Constraints(Text.StartsWith("System.Exception:"));

   Expect.Call(simpleDialogHandler.HandleDialog(dialog)).Return(true);

 

   mocks.ReplayAll();

 

   Logger.LogWriter = mockLogWriter;

 

   DialogWatcher dialogWatcher = new DialogWatcher(0);

   dialogWatcher.Add(throwExceptionDialogHandler);

   dialogWatcher.Add(simpleDialogHandler);

 

   dialogWatcher.HandleWindow(dialog);

 

   mocks.VerifyAll();

}

time to read 2 min | 285 words

Well, a bit late, there is a new beta out. Don't bother to looks for beta 3, it doesn't exists, turned out that I named the beta 2 "beta 3", so I skipped a number.

Changes:

  • Regression with closed generic types inheriting from open generic types that contains generic properties of the generic type, if the property is overriden
  • Fixed a problem with the new semantics of CallOriginalMethod
  • Fixed a problem mocking internal types that are not nested
  • Misleading exception when you pass a mock object of type that override ToString() to an unexpected method.
  • BREAKING CHANGE: Moved all the constraints to Rhino.Mocks.Constraints namespace. This was done to avoic conflicts with NUnit and MbUnit's new assert syntax.

Both NUnit and MbUnit are moving to support constaints for assertions, this means that we are getting conflicts. I already asked both NUnit and MbUnit devs to move their constaints to separate namespace, and moving the constaints to a separate namespace in Rhino Mocks as well would reduce the possibility of conflicts. Note that this change merely means that you need to add a "using Rhino.Mocks.Constraints;", annoying for people with a lot of tests, but I believe that this is a good decision.

If nothing goes wrong, I hope to release 3.0 next week. Source and binaries are here.

time to read 2 min | 286 words

Took a bit longer than I anticipated, since people found some really hard bugs with regards to the generics support. I now know a lot more than I ever wanted to about generics, and I considered myself an expert before-hand.

Anyway, the new bits have:

  • Improved support for wacky generics scenarios. Thanks to James and Thierry.
  • Better support for types having non inheritable attributes that cannot be easily replicated. Thanks to Aaron.
  • Better support for types implementing interfaces by using a base class that is located in another assembly.* Thanks to Aaron.
  • Included XML Documentation files.
  • All merged assemblies are not marked internal, to save your from collisions if you are using the Castle bits yourself.

Changes:

The CallOriginalMethod() was deprecated, you are now encouraged to use CallOriginalMethod(OriginalMethodOptions.NoExpectation) or CallOriginalMethod(OriginalMethodOptions.CreateExpectation) instead. The reasoning behind the change is that currently CallOriginalMethod looks like it create an expectation, but it doesn't really does it, s it is better to be explicit about the whole thing. Thanks for Enrst for pointing it out to me.

As usual, the binaries and source are here.

* If you understood what that meant...

time to read 1 min | 100 words

Take a look here to see what it takes to solve my previous challange. It was extremely hard to get it to work in all scenarios, and I am pretty sure that there are additional edge cases that I have not thought of, but for now, all the tests are green. I also have a 100% repreducable (on several machines) VS crashing bug, which is about the fifth that I know of.

I actually started to put MsgBox.Show() in the code, and had a serious JavaScript deja-vu as a result...

time to read 1 min | 179 words

The guys from Eleutian had done it again, with a post that explains how you can use Windor and Rhino Mocks in order to make it easy to create the tests.

Jacob is raising some concerns about this approach:

Speed/peformance? Does making the container such an integral part of the test fixtures hurt performance? Setup has to be longer when we're creating the container the way we are. Does this matter? Only as long as the time saved when writing tests is larger than the time it takes to run them, which I'm sure is the case...

Windsor setup is generally fast enough, but doing it per test is probably going to slow the tests down. It certainly makes the tests a lot easier to write.

Oh, and Beta 2 of Rhino Mocks 3.0 should be out later today...

time to read 2 min | 320 words

Took a while, and a lot of effort, but it is here. Thanks to Hammett who did all the hard work making Dyanmic Proxy 2.

New stuff:

  • Generic Methods (at last!)
  • Support arrays of value types as out parameters
  • Support non-CLS Compliant value types such as UInt64
  • Better error messages when using generic delegate methods on generic types
  • Generally faster

Compatability:

  • There should be zero problems moving to the new release. If you do get into such a problem, I would like to hear about it.
  • It supports only the .Net 2.0 framework. This is because Dynamic Proxy 2 is currently 2.0 only, which is due to change at a future date.

Why beta?

  • While I am convinced that this a working release, I want to aovid a flurry of 3.0.1, 3.0.2, etc in the case it is not. In addition to that, I made a fairly big change under the cover, and I would like to test that in the field first.r

Source and binaries are here.

Update: I forgot to merge the Castle.Core assembly in, if you had any problems with it, please download the file again.

time to read 1 min | 82 words

(Image from clipboard).png

Right now I got 99.5%+, which should be enough (this means that I got three lines that aren't covered by tests, and I think that this is acceptible. Next in line is to update the documentation and push the build out.

As it looks now, there will not be a 1.1 release this time. If it is a major obstacle for you, please let me know.

time to read 23 min | 4531 words

I just got a bing sound from the computer, telling me that an important message has arrived:

------ Test started: Assembly: Rhino.Mocks.Tests.dll ------

486 passed, 0 failed, 0 skipped, took 6.56 seconds.

Yup, that is correct. All, but all, of Rhino Mocks tests are currently passing. What is so suprising about Rhino Mocks passing all its tests? The surprising part is that now it is running on Dynamic Proxy 2, which means that there is support for mocking Generic Methods! This has long been Rhino Mock's weakest point, and it is now working!

Check out the syntax:

[Test]

public void CanCreateMockOfInterfaceWithGenericMethod()

{

       MockRepository mocks = new MockRepository();

       mocks.CreateMock<IFactory>();

}

 

[Test]

public void CanSetExpectationsOnInterfaceWithGenericMethod()

{

       MockRepository mocks = new MockRepository();

       IFactory factory = mocks.CreateMock<IFactory>();

       Expect.Call(factory.Create<string>()).Return("working?");

       mocks.ReplayAll();

       string result = factory.Create<string>();

       Assert.AreEqual("working?",result, "Should have worked, hm..." );

       mocks.VerifyAll();

}

 

[Test]

[ExpectedException(typeof(ExpectationViolationException),@"IFactory.Create<System.Int32>(); Expected #1, Actual #1.

IFactory.Create<System.String>(); Expected #1, Actual #0." )]

public void WillGetErrorIfCallingMethodWithDifferentGenericArgument()

{

       MockRepository mocks = new MockRepository();

       IFactory factory = mocks.CreateMock<IFactory>();

       Expect.Call(factory.Create<string>()).Return("working?");

       mocks.ReplayAll();

       factory.Create<int>();

}

 

 

[Test]

[ExpectedException(typeof(InvalidOperationException),"Type 'System.Int32' doesn't match the return type 'System.String' for method 'IFactory.Create<System.String>();'")]

public void WillGiveErrorIfThereIsTypeMismatchInGenericParameters()

{

       MockRepository mocks = new MockRepository();

       IFactory factory = mocks.CreateMock<IFactory>();

       Expect.Call(factory.Create<string>()).Return(1);

}

 

[Test]

[ExpectedException(typeof(ExpectationViolationException), "IFactory.Create<System.String>(); Expected #1, Actual #0.")]

public void WillGiveErrorIfMissingCallToGenericMethod()

{

       MockRepository mocks = new MockRepository();

       IFactory factory = mocks.CreateMock<IFactory>();

       Expect.Call(factory.Create<string>()).Return("working?");

       mocks.ReplayAll();

       mocks.VerifyAll();

}

What remains to do is to run some more tests (feel free to suggest some), implement some more accumolated bug fixes / feature requests that I have gathered, and release!

The last release was about three months ago, which is probably the longest time that Rhino Mocks had without a release. I am a bit afraid of release it, to tell the truth, every time that I do, I end up release another version shortly, with additional features/bug fixes. The problem is that the algorithm is recursive... :-)

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. RavenDB 7.1 (7):
    11 Jul 2025 - The Gen AI release
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}