我目前正在开发一个项目,其中包含使用 RhinoMocks 模拟对象的测试。自从 3.6.0 升级到 RhinoMocks 3.6.1 以来,以前工作的项目代码在测试期间失败。问题似乎是由版本之间模拟对象的行为改变引起的。生成的Mock对象现在是Castle Proxy对象,看起来不可反映。以前可以通过反射从模拟对象收集MethodInfo,这似乎不再是这种情况。我应该以不同的方式设置我的模拟吗?
以下是一个非常简化的例子:
给出一个被模拟的界面
public interface IValidator<in T>
{
bool Validate(T obj);
}
在测试代码中,模拟是在期望中创建的:
var validator = MockRepository.GenerateMock<IValidator<string>>();
validator.Expect(v => v.Validate(Arg<string>.Is.Equal("input")))
.Return(true);
...
// the validator object is then passed into a consumer and assertions
// are checked to be sure the consumer and validator appropriately
// behave (outside scope of question)
在使用者类中,完成反射以从接口获取“Validate”方法,以便在标准执行期间调用:
var method = validator.GetType()
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
当使用 RhinoMocks 的更新版本时,问题的关键是method
现在为空,因为反射似乎不再起作用。
我的问题的根源是无法反映Rhino / Castle生成的代理对象,而我所拥有的实例都无法进行显式转换。
答案 0 :(得分:0)
我知道这可能让我脸红了。
但是,如果你是一个泛型类,你可以很容易地做类似
var method = typeof(IValidator<T>).GetType()
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
此外,如果项目非常庞大且有大量测试和嘲讽,这可能会造成大量的返工:(
修改强>
好的第2轮:) :)
问题似乎在于mock是一个动态类,实际上似乎没有那个方法。
如何使用GetMethod创建一个接口(ITypeHelper),它具有许多用于获取类型和方法的包装器方法。
通常这些只是直接调用这些方法(以免造成任何性能损失),但在测试期间,您可以将您的ITypeHelper实现替换为MockTypeHelper(通过更改容器中的注册或其他一些机制)。
public class RhinoMocks_33901386
{
//public static ITypeHelper TypeHelper = new TypeHelper();
//use when testing
public static ITypeHelper TypeHelper = new MockTypeHelper();
public static void Run()
{
var validator = MockRepository.GenerateMock<IValidator<string>>();
validator.Expect(v => v.Validate(Arg<string>.Is.Equal("input"))).Return(true);
var method = TypeHelper.GetMethod(validator.GetType(), "Validate");
var result = (bool) method.Invoke(validator, new object[] {"input"});
Console.WriteLine(result);
Console.WriteLine("Done");
Console.ReadLine();
}
}
public interface IValidator<in T>
{
bool Validate(T obj);
}
public interface ITypeHelper
{
MethodInfo GetMethod(Type self, string name);
}
public class TypeHelper : ITypeHelper
{
public virtual MethodInfo GetMethod(Type self, string name)
{
return self.GetMethod(name);
}
}
public class MockTypeHelper : ITypeHelper
{
public virtual MethodInfo GetMethod(Type self, string name)
{
if (typeof(IMockedObject).IsAssignableFrom(self) && self.BaseType == typeof(object))
{
self = self.GetInterfaces()
.First(x => x != typeof(IMockedObject) && x != typeof(ISerializable) && x != typeof(IProxyTargetAccessor));
}
return self.GetMethod(name);
}
}
希望我变暖; p
答案 1 :(得分:0)
似乎RihnoMocks或Castle DynamicProxy已经改变了它在内部的工作方式。正如@ sQuir3l指出的那样,它似乎在内部使用动态对象。
在这种特殊情况下,您可以通过访问基础接口类型来解决此问题:
var method = ((IMockedObject)validator).ImplementedTypes
.Single(type => type == typeof(IValidator<string>))
.GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);