是否可以使用 Rhino.Mocks 模拟静态方法?如果 Rhino 不支持这一点,是否有模式或其他东西可以让我完成同样的事情?
6 回答
是否可以使用 Rhino.Mocks 模拟静态方法
不,这是不可能的。
TypeMock 可以做到这一点,因为它利用 CLR 分析器来拦截和重定向调用。
RhinoMocks、NMock 和 Moq 无法做到这一点,因为这些库更简单;他们不使用 CLR 分析器 API。它们更简单,因为它们使用代理来拦截虚拟成员和接口调用。这种简单性的缺点是它们不能模拟某些东西,例如静态方法、静态属性、密封类或非虚拟实例方法。
将静态方法调用包装在另一个类的虚拟实例方法中,然后将其模拟出来。
如果不能使用 TypeMock 拦截方法调用,推荐使用的模式是创建一个代理,转发到您有兴趣测试的非虚拟或静态方法,然后在代理上设置期望。为了说明,考虑以下类。
class TypeToTest
{
public void Method() { }
}
interface ITypeToTest
{
void Method();
}
class TypeToTestProxy : ITypeToTest
{
TypeToTest m_type = new TypeToTest();
public void Method() { m_type.Method(); }
}
通过创建此代理,您现在可以使用 anITypeToTest
代替您传递或设置TypeToTest
实例的位置,确保默认实现在TypeToTestProxy
转发到实际实现时使用 。然后,您可以在测试代码中创建一个模拟ITypeToTest
并相应地设置期望。
请注意,创建这些代理可能非常乏味、容易出错且耗时。为了解决这个问题,我维护了一个库和一组工具,为您生成包含这些类型的程序集。请参阅此页面了解更多信息。
我所知道的唯一支持模拟静态的模拟框架是 TypeMock。
正如 Rytmis 建议的那样,您需要将静态数据包装在可以模拟的东西(即具有虚拟方法或接口的实例类)中。
这是 Rhino Mocks 最大的缺点。我不知道 Rhino Mocks 甚至有可能在没有重新概念它如何进行模拟的情况下实现这个。
我一直在使用 moq 进行模拟,我认为我们不能使用它来模拟静态成员,因为 moQ 为目标(类或接口)创建了一个新代理。因此,只有可继承的成员(在类的情况下是虚拟的,在接口方面是公共的)可以被模拟。显然,静态成员不是继承的,因此存在问题。