Hi,
If I try to create a mock or a stub that uses the following interface
public interface ITest
{
TView Show<TController, TView>(ViewInfo info, TController
controller)
where TController : class, IController
where TView : IView<TController>;
}
then I get an exception when the test is run in debug mode. The call
stack associated with the exception is listed below. If the test is
run outside of the debugger or if the second constraint is removed,
the exception is not thrown. Can anyone help please?
Call stack :
failed: An attempt was made to load a program with an incorrect
format. (Exception from HRESULT: 0x8007000B)
System.BadImageFormatException
Message: An attempt was made to load a program with an
incorrect format. (Exception from HRESULT: 0x8007000B)
Source: mscorlib
StackTrace:
at System.Reflection.Emit.TypeBuilder._TermCreateClass(Int32
handle, Module module)
at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock()
at System.Reflection.Em it.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
theInterface, Type[] interfaces, ProxyGenerationOptions options)
at
Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyTypeWithoutTarget(Type
theInterface, Type[] interfaces, ProxyGenerationOptions options)
at
Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type
theInterface, Type[] interfaces, ProxyGenerationOptions options,
IInterceptor[] interceptors)
at
Castle.DynamicProxy.ProxyGenerator.CreateInterfaceProxyWithoutTarget(Type
theInterface, Type[] interfaces, 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.GenerateStub(Type type, Object[]
argumentsForConstructor)
at Rhino.Mocks.MockRepository.GenerateStub[T](Object[]
argumentsForConstructor)
I still can't work out how to do this.....
IServiceProvider mockProvider =
Mocks.DoSomething<IServiceProvider>(originalServiceProvider);
mockProvider.GetService(typeof(IMyService)).Return(mockMyService);
Where a call to mockServiceProvider(typeof(IMyService)) will return a
specific value, but any other call will pass the request to
originalServiceProvider.
What do I have to do?
Thanks
Pete
The exact test mocks HttpContext etc and runs an action on a controller. It
checks that the changes are not saved to the DB if any constraints on the
object being updated are broken.
//First create a validation constraint that is always false
IConstraint constraint = new Constraint();
constraint.Expression = "false";
constraint.Name = "Cannot save";
IList<IConstraint> constraints = new List<IConstraint>();
constraints.Add(constraint);
//Mock the IConstraintProvider service to return this list
IConstraintProvider mockConstraintProvider =
Mocks.Create<IConstraintProvider>();
SetupResult.For(mockConstraintProvider.GetConstraints(null)).IgnoreParameters().Return(constraints);
//Mock the service provider to always use the mock constraint provider
IEcoServiceProvider mockServiceProvider =
Mocks.Create<IEcoServiceProvider>();
SetupResult.For(mockServiceProvider.GetEcoService<IConstraintProvider>()).Return(mockConstraintProvider);
Then I create my controller + mock the http stuff.....
AccountController controller =
AccountController.CreateTestController(mockServiceProvider);
(mock http)
Mocks.ReplayAll();
controller.SaveChanges(1, "Mr", "Peter", "Morris");
(asserts here).
The thing is that the controller action does something like this
01: Get the object instance from the DB
02: Apply the changes to the object
03: Use IConstraintProvider to get constraints and check the values are
valid
04: Save changes or undo changes.
The persistence framework I use depends on IEcoServiceProvider for creating
objects, reading cache values, plus all sorts of other stuff. So instead of
having to do a SetupResult.For<> on every possible combination I would just
like my mockServiceProvider to pass the request onto the RealServiceProvider
unless I explicitly set a result, e.g.
IEcoServiceProvider mockServiceProvider =
Mocks.SomethingHere<IEcoServiceProvider>(RealServiceProvider);
I hope that's clear :-)
Pete
> http://www.ayende.com/Wiki/(S(xy3xruulb1ifjlnfmzhwghvy))/Rhino+Mocks+Partial+Mocks.ashx
I have seen this before. It seems to mock a class type, I need to partially
mock a specific instance implementing an interface.
It needs to be a specific instance because there are
IObjectFactory : Creates objects
ICacheService : Holds property values of the objects
IOclService : Performs OCL evaluation on the cache
and so on. The IEcoServiceProvider is always passed to me, I never create
it myself. As a consequence I need to partially mock an instance of (some
unknown object type) which implements IEcoServiceProvider and by pass only
some of the calls to GetEcoService<T>().
At the moment I am having to set up mocks for every service and pass them on
to the original service, and that's too much work :-)
Pete
My point is that there are so many services to pass through, not only that
but I would also need to be aware of any additional services being added
etc. All I want to do is to say "Operate as normal, but when
IConstraintProvider is retrieved return this mock object instead".
If this is not already possible I hope you will consider it as a feature,
e.g.
IEcoServiceProvider mockProvider =
mocks.CreatePassThrough<IEcoServiceProvider>(RealProvider);
Expect.Call(mockProvider.GetEcoService<IConstraintProvider>()).Return(mockConstraintProvider);
2 lines of code, does everything required. To mock the object factory +
cache + persistence + transactionservice etc would all be too much work, and
adding passthroughs manually would not only be a lot of work but also prone
to mistakes whenever a new service is added (which I might not even be aware
of).
Pete
Feeling free I have no problem. Feeling able.....hmm :-)
Seriously though I have only been using your mocking stuff for a short
period, I think trying to alter the code at this stage would be a bit
premature.
Pete
I can't see info on your homepage regarding your trunk url + the procedure
for submitting patches. I presume you have it documented somewhere, would
you mind sending the URL please?
Thanks
Pete
I overloaded MockInterface() to allow an additional parameter "object
target". The
//Provide original behaviour
private object MockInterface(CreateMockState mockStateFactory, Type type,
Type[] extras)
{
return MockInterface(mockStateFactory, type, extras, null);
}
private object MockInterface(CreateMockState mockStateFactory, Type type,
Type[] extras, object target)
{
object proxy;
List<Type> implementedTypesForGenericInvocationDiscoverability = new
List<Type>(extras);
implementedTypesForGenericInvocationDiscoverability.Add(type);
RhinoInterceptor interceptor = new RhinoInterceptor(this, new
ProxyInstance(this,
implementedTypesForGenericInvocationDiscoverability.ToArray()));
ArrayList types = new ArrayList();
types.AddRange(extras);
types.Add(typeof(IMockedObject));
if (target == null)
//Original behaviour
proxy =
generator.CreateInterfaceProxyWithoutTarget(type,
(Type[])types.ToArray(typeof(Type)), interceptor);
else
//New behaviour
proxy =
generator.CreateInterfaceProxyWithTargetInterface(type, target, new
IInterceptor[] { interceptor });
IMockState value = mockStateFactory((IMockedObject)proxy);
proxies.Add(proxy, value);
return proxy;
}
I have no idea if this is the correct approach or not but it's my first
attempt :-)
Anyway, my problem is that CreateInterfaceProxyWithTargetInterface returns
an object that cannot be cast to IMockedObject. I also tried
proxy =
generator.CreateInterfaceProxyWithTarget(type, extras, target, new
IInterceptor[] { interceptor } );
and that does exactly the same thing.
Some pointers would be appreciated :-)