无法让RhinoMocks发出遵循generics类型限制规则的模拟

所以,使用NUnit和RhinoMocks:

//Defines basic behavior of all persistable domain objects public interface IDomainObject {...} //defines domain objects specific to the Security DB public interface ISecurityDomainObject : IDomainObject {...} //Defines a basic transactional data Repository; there are multiple implementors //which each close TRest to the interface that defines their DB's domain classes public interface IRepository : IDisposable where TRest:IDomainObject { IUnitOfWork BeginUnitOfWork(); void CommitUnitOfWork(IUnitOfWork unitOfWork); void RollBackUnitOfWork(IUnitOfWork unitOfWork); void Save(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest; IQueryable QueryFor(IUnitOfWork unitOfWork) where T :class, TRest; } public interface ISecurityRepository:IRepository {} public class SecurityRepository:ISecurityRepository ... //This line breaks when run in an NUnit test var securityRepository = MockRepository.GenerateMock(); ... 

我得到的错误是:

 System.TypeLoadException : Method 'Save' on type 'ISecurityRepositoryProxyb8e21deb3cb04067a01ac5b63f7045af' from assembly 'DynamicProxyGenAssembly2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' tried to implicitly implement an interface method with weaker type parameter constraints. at System.Reflection.Emit.TypeBuilder.TermCreateClass(RuntimeModule module, Int32 tk, ObjectHandleOnStack type) at System.Reflection.Emit.TypeBuilder.CreateTypeNoLock() at System.Reflection.Emit.TypeBuilder.CreateType() 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.DynamicMock(Object[] argumentsForConstructor) at Rhino.Mocks.MockRepository.c__DisplayClass7`1.b__6(MockRepository r) at Rhino.Mocks.MockRepository.CreateMockInReplay(Func`2 createMock) at Rhino.Mocks.MockRepository.GenerateMock(Object[] argumentsForConstructor) at CSHD.Tests.Unit.Presentation.LoginTests.TestAuthenticationFails() in LoginTests.cs: line 138 

当尝试针对具体类生成模拟时,我得到了类似的错误,这次是在QueryFor()方法上。 如果我尝试重新定义在ISecurityRepository接口中使用TRest的方法,我会得到一个“System.BadImageFormatException:尝试加载一个格式不正确的程序。(HRESULTexception:0x8007000B)”这看起来像一个倒退。

我认为核心问题是RhinoMocks对通用参数被用作generics类型限制感到困惑。 我不知道它在哪里被混淆,因此我不知道如何或如果我不能混淆它。 我有足够的集成测试覆盖率,如果我绝对必须,我可以忽略这些失败的unit testing,但显然我宁愿修复它们,如果可以的话。 你的意见?

看起来这是一个由Castle.DynamicProxy引起的已知问题,该问题已在该项目的最新主干中修复,但在最新的Rhino Mocks版本中仍然存在问题:

http://groups.google.com/group/rhinomocks/browse_thread/thread/2c1b53bf66b77b8e/ad09a6cd1e304a93

如果您有冒险精神,可以使用最新的DynamicProxy构建自己的Rhino Mocks,并且应该修复它。

看起来像Castle Dynamic Proxy(Rhino Mocks用于代理生成)并没有正确生成代理类,因为您已经定义了通用参数。 如果您定义这样的IRepository,则可以生成代理(因此也可以生成模拟):

 public interface IRepository : IDisposable where T : class, IDomainObject { IUnitOfWork BeginUnitOfWork(); void CommitUnitOfWork(IUnitOfWork unitOfWork); void RollBackUnitOfWork(IUnitOfWork unitOfWork); void Save(T domainObject, IUnitOfWork unitOfWork); IQueryable QueryFor(IUnitOfWork unitOfWork); } 

如果你真的需要它以另一种方式定义,你将不得不提交Rhino Mocks的错误。