Tutorial :How do you mock UnitOfWork from Rhino.Commons?



Question:

My application is using Rhino.Commons - NHRepository and UnitOfWork. I like the With.Transaction() syntax for transactions and have been using it for some time.

But I ran into a problem - how do I mock a UnitOfWork for testing? Especially this is causing trouble for me:

With.Transaction(() => Repositories.TwinfieldSpooler.Update(spool));  

I can mock repositories with Rhino.Mocks, but how can I easily mock UnitOfWork for this kind of code?


Solution:1

With.Transaction uses UnitOfWork.Current property. UnitOfWork is a static class -- you can't mock it with RhinoMocks.

UnitOfWork.Current is a public static property, so you can swap it out. Unfortunately, the setter is internal.

I see 3 options for you:

  • Modify the Rhino.Commons source to make UnitOfWork.Current setter public, and set it in your unit test.

  • Use reflection to set the UnitOfWork.Current to your fake unit of work.

  • Since UnitOfWork.Current internally uses Local.Data to find the current transaction, you should be able to go:

    Rhino.Commons.Local.Data[UnitOfWork.CurrentUnitOfWorkKey] = myFakeUnitOfWork;

One bit of good news is that UnitOfWork.Current is an IUnitOfWork, and RhinoMocks can easily fake interfaces.

I must finish by saying, I'm not very familiar with Rhino.Commons, so Ayende might have built a proper way of faking UnitOfWork. If this is super-important to you, you ought to ask in the Rhino discussion groups.


Solution:2

I had a similar need, because I wanted to test the logic around the persistence without actually testing the persistence of the data. I found I could mock/stub the UnitOfWork easily using these 2 lines in the SetUp portion of my tests:

IUnitOfWork theStubUnitOfWork = MockRepository.GenerateStub<IUnitOfWork>();  UnitOfWork.RegisterGlobalUnitOfWork(theStubUnitOfWork);  


Solution:3

Thanks, but I've actually decided to ignore mocking of the Rhino infrastructure. I found this post by Ayende http://ayende.com/Blog/archive/2009/04/28/nhibernate-unit-testing.aspx on using a sqlite database rebuilt with every test. This has been a great solution!


Solution:4

Just an additional bit of info for others: Ogre Psalm33 has mentioned how to stub the UnitOfWork, but if you also want With.Transaction to work, you can additionally stub a RhinoTransaction:

IUnitOfWork stubUnitOfWork = MockRepository.GenerateStub<IUnitOfWork>();  RhinoTransaction stubTx = MockRepository.GenerateStub<RhinoTransaction>();  stubUnitOfWork.Expect(x => x.BeginTransaction(System.Data.IsolationLevel.Unspecified)).IgnoreArguments().Return(stubTx);  UnitOfWork.RegisterGlobalUnitOfWork(stubUnitOfWork);  

I recall seeing a note from Ayende somewhere that he generally used With.Transaction as a last resort only, when he couldn't use his preferred Castle Automatic Transaction Management.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »