假设我有一个由第三方创建的Castle.DynamicProxy对象。在这种情况下Rhino.Mocks。
var rhinoObj = MockRepository.GenerateMock<IMyType>();
出于某种原因,我希望能够使用Rhino生成的这个对象并添加另一个拦截器,这样我就可以在不使用Rhino本身的情况下对其进行操作。
我理解这可能看起来很奇怪,它是一个模拟库,我自己写的,我想要与使用Castle的其他模拟框架集成,例如Rhino。
我试过了:
generator.CreateInterfaceProxyWithTarget(rhinoObj, new MyInterceptor())
但是当我希望使用像.Stub(..)这样的东西时,Rhino会抱怨这不是一个模拟对象 - 所以很明显犀牛拦截器会被覆盖。
答案 0 :(得分:0)
我知道这是一个古老的问题,但我有同样的问题。 2天前阅读我自己的答案将为我节省几个小时...
Rhino.Mocks在城堡动态代理的帮助下,根据您的界面生成一个新类型,并创建一个实例并将其返回给您。此实例还用作rhino.mock内部键,用于查找所有模拟物(断言,返回值等)。
现在,您将围绕rhino.mock对象创建一个代理(即:另一个新类型和另一个新实例),并且按实例查找不再起作用。您需要某种方式的原始对象。
您需要使原始对象远离rhino.mocks。外观如何取决于您的整体设置。也许所有实例的创建都要经过一个中央存储库,您可以添加方便的访问器方法,例如:
internal interface IMockRepository
{
void Add(object key, object mock);
T GetMock<T>(T key);
object GetMock(object key);
}
这应该可以欺骗任何模拟框架,而不仅仅是rhino.mocks。不利的一面是额外的基础结构和样板代码。还有你create a proxy around a proxy的尴尬感。
(基于this答案):Rhino.mocks还使用城堡动态代理和拦截器。也许我们可以潜入我们自己的拦截器?我们可以!
var mock = Rhino.Mocks.MockRepository.GenerateStub(type);
dynamic dyn = mock;
dyn.__interceptors = new[] {new MyInterceptor(), dyn.__interceptors[0]};
您需要使用Castle.Core.Interceptor的IInterceptor和IInvocation而不是Castle.DynamicProxy,但是接口是相同的。原始代理必须排在最后。
这依赖于rhino.mocks-internals,它在将来的任何发行版中可能会更改,恕不另行通知。但是我认为可以断定(a)rhino.mocks将继续使用城堡动态代理,并且(b)动态代理在将来也将是动态的。因此,如果出现问题,应该可以修复。
这更“棘手”,但我使用此解决方案。没有“代理的东西”,也没有样板。