2010-12-07 36 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