2010-12-07 41 views
5

所以:使用NUnit和RhinoMocks不能让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<TRest> : IDisposable where TRest:IDomainObject 
{ 
    IUnitOfWork BeginUnitOfWork(); 
    void CommitUnitOfWork(IUnitOfWork unitOfWork); 
    void RollBackUnitOfWork(IUnitOfWork unitOfWork);   
    void Save<T>(T domainObject, IUnitOfWork unitOfWork) where T : class, TRest;   
    IQueryable<T> QueryFor<T>(IUnitOfWork unitOfWork) where T :class, TRest; 
} 

public interface ISecurityRepository:IRepository<ISecurityDomainObject> {} 

public class SecurityRepository:ISecurityRepository 

... 

//This line breaks when run in an NUnit test 
var securityRepository = MockRepository.GenerateMock<ISecurityRepository>(); 
... 

我得到的错误是:

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.<GenerateMock>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:尝试加载格式不正确的程序(来自HRESULT的异常:0x8007000B)”,这看起来像是一个倒退的步骤。

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

回答

1

Castle Dynamic Proxy(Rhino Mocks用于生成代理服务器)看起来没有根据您定义泛型参数的方式正确生成代理类。您可以生成一个代理(因此一个模拟),如果你定义IRepository这样,而不是:

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

如果你真的需要它规定的其他方式,你必须文件,犀牛制品的错误。

+0

我真的很需要它定义我拥有它的方式。我有几个IRepository的实现,每个都针对不同的数据库(我没有组成模式,我只是继承了它),每个实现都与域的不同子集一起工作。我在编译时确定的定义是,代码不能试图要求存储库使用不属于其模式一部分的对象。因为Save和QueryFor无法知道具体类型(他们需要),所以您在那里基本上需要每个域对象的存储库,因为T不能被定义为ISecurityDomainObject。 – KeithS 2010-12-07 23:47:19

+0

够公平的。问题在于Rhino Mocks中没有发生异常,但Castle DynamicProxy中发生异常。我检查了Moq(它使用比Rhino MOCKS更新的Castle DynamicProxy版本),它也受到这种限制。目前,这个界面不能使用Rhino Mocks或Moq进行模拟。为了解决这个问题,Castle DynamicProxy必须解决潜在的问题。希望我对你有更好的答案。 – 2010-12-08 00:48:19