views:

248

answers:

2

I'm trying to set up blade unit tests in an MVC Turbine-derived site. The problem is that I can't seem to mock the IServiceLocator interface without hitting the following exception:

System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)
at System.Reflection.Emit.TypeBuilder._TermCreateClass(Int32 handle, Module module)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Emit.TypeBuilder.CreateType()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
at Castle.DynamicProxy.Generators.Emitters.AbstractTypeEmitter.BuildType()
at Castle.DynamicProxy.Generators.InterfaceProxyWithTargetGenerator.GenerateCode(Type proxyTargetType, Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.DefaultProxyBuilder.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, IInterceptor[] interceptors)
at Rhino.Mocks.MockRepository.MockInterface(CreateMockState mockStateFactory, Type type, Type[] extras)
at Rhino.Mocks.MockRepository.CreateMockObject(Type type, CreateMockState factory, Type[] extras, Object[] argumentsForConstructor)
at Rhino.Mocks.MockRepository.Stub(Type type, Object[] argumentsForConstructor)
at Rhino.Mocks.MockRepository.<>c__DisplayClass1`1.<GenerateStub>b__0(MockRepository repo)
at Rhino.Mocks.MockRepository.CreateMockInReplay<T>(Func`2 createMock)
at Rhino.Mocks.MockRepository.GenerateStub<T>(Object[] argumentsForConstructor)
at XXX.BladeTest.SetUp()

Everything I search for regarding this error leads me to 32-bit vs. 64-bit DLL compilation issues, but MVC Turbine uses the service locator facade everywhere and we haven't had any other issues, just with using Rhino Mocks to attempt mocking it.

It blows up on the second line of this NUnit set up method:

IRotorContext _context;
IServiceLocator _locator;

[SetUp]
public void SetUp()
{
    _context = MockRepository.GenerateStub<IRotorContext>();
    _locator = MockRepository.GenerateStub<IServiceLocator>();
    _context.Expect(x => x.ServiceLocator).Return(_locator);
}

Just a quick aside; I've tried implementing a fake implementing IServiceLocator, thinking that I could just keep track of calls to the type registration methods. This won't work in our setup, because we extend the service locator's interface in such a way that if the type isn't Unity-based, the registration logic is not invoked.

+1  A: 

Yes, I've ran into the same issue with RhinoMocks while testing the runtime for Turbine also. I hate to say it but I worked around the issue by providing my own fake for IServiceLocator for where I needed, but as you explained, you can't do that. :(

I'm not following this piece from your question, "if the type isn't Unity-based"??

Javier Lozano
Javier - thanks for the quick feedback; for the record, MVC Turbine is fantastic and I appreciate how easy it makes SoC for everyone working on our site.We extended the IServiceLocator interface to accept lifetime manager objects. Since they are Unity-specific, the call only executes successfully if the underlying object is a UnityServiceLocator. We added a layer between our site and MVC Turbine that defines and registers high-level stuff (e.g., logging, cookie management) in its global HTTP app, so we felt lower-level mappings should be defined in blades. Any thoughts on a better way?
Brandon Linton
So after some intense refactoring I made it so that we can add type registrations to a static container on the global web application in its static constructor. That way I don't have to do my interface extension hacking.
Brandon Linton
Sorry for being MIA on this question but I wasn't getting notified on additions. :)How much of a refactoring did you have to do?
Javier Lozano
No problem, same here actually. We ended up with a static unity container at our framework layer, which does the high-level registrations. The inheriting http app client performs its registrations from the static constructor too. I still had to make a fake UnityContainer so that I could verify lifetime was being set appropriately. It worked out well in the end because we could make the ordering of type registration clear and centralized. Plus I feel less dirty for writing unnecessary ServiceLocator extensions :)
Brandon Linton
Awesome, great to hear! if you don't mind me asking, what type of application are you using Turbine for?
Javier Lozano
Sadly I can't go into detail (hence my XXX-ed out blade test above...I swear it's a reputable site!). I'll follow up sometime when it's live :). But there are other concurrent MVC site initiatives starting up where I am and I continue to point them in Turbine's direction...really great stuff.
Brandon Linton
I completely understand, so no worries there. The only reason I ask is because I always find it interesting on how people use the project to their needs. I'm glad it's working out for you! If you have more specific questions or would like ot chat with others about the project, checkout the Google Group - http://groups.google.com/group/mvcturbine
Javier Lozano
Almost forgot! We've moved from RhinoMocks to Moq for our mocking and stubs for the internal Turbine tests. The mocking for IServiceLocator is no longer an issue. IF you're not tied to RhinoMocks, I suggest you check out and see if it works for you.
Javier Lozano
Brandon, did you get the site you were building on Turbine published? just curious ;)
Javier Lozano
+1  A: 

This has been fixed in Moq v4.0 beta. The issue was in Castle DynamicProxy 2.1 when creating dynamic proxies for interfaces with generic constraints.

http://code.google.com/p/moq/issues/detail?id=177

Igor Zevaka
+1 Interesting...I didn't realize Castle was the underlying framework for both Moq and RhinoMocks until I looked at that and reread my stack trace
Brandon Linton