C# 测试期间无法从rhino模拟接口检索MethodInfo

C# 测试期间无法从rhino模拟接口检索MethodInfo,c#,reflection,mocking,rhino,C#,Reflection,Mocking,Rhino,我目前正在进行一个项目,其中包括使用RhinoMocks模拟对象进行测试。由于从3.6.0升级到RhinoMocks 3.6.1,以前工作的项目代码在测试期间失败。这个问题似乎是由版本之间模拟对象行为的改变引起的。生成的模拟对象现在是看起来不可反射的Castle代理对象。以前,可以通过反射从模拟对象收集MethodInfo,但现在似乎不再是这样了。我应该以不同的方式设置模拟吗 下面是一个大大简化的示例: 给定一个要模拟的接口 public interface IValidator<in T

我目前正在进行一个项目,其中包括使用RhinoMocks模拟对象进行测试。由于从3.6.0升级到RhinoMocks 3.6.1,以前工作的项目代码在测试期间失败。这个问题似乎是由版本之间模拟对象行为的改变引起的。生成的模拟对象现在是看起来不可反射的Castle代理对象。以前,可以通过反射从模拟对象收集MethodInfo,但现在似乎不再是这样了。我应该以不同的方式设置模拟吗

下面是一个大大简化的示例:

给定一个要模拟的接口

public interface IValidator<in T>
{
    bool Validate(T obj);
}
问题的关键是当使用Rhinomock的更新版本作为反射似乎不再工作时,
方法
现在为空


我的问题的根源是,当我只有实例无法进行显式转换时,无法对Rhino/Castle生成的代理对象进行反思。

我知道这可能会让我脸上挨一拳。
但是如果你在一个泛型类中,你可以很容易地做一些类似的事情

var method = typeof(IValidator<T>).GetType()
    .GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
var method=typeof(IValidator).GetType()
.GetMethod(“验证”,BindingFlags.Public | BindingFlags.Instance);
此外,如果项目非常大,并且有大量的测试和模拟,这可能需要大量的返工:(

编辑:
Ok第二轮:)

问题似乎在于mock是一个动态类,实际上似乎没有该方法

与其使用GetMethod,不如创建一个接口(ITypeHelper),该接口有许多用于获取类型和方法的包装器方法

通常,这些方法只是直接调用这些方法(以便不会造成任何性能损失),但在测试期间,您可以将ITypeHelper的实现替换为MockTypeHelper(通过更改容器中的注册或其他机制)

公共类RhinoMocks_33901386
{
//公共静态ITypeHelper TypeHelper=新的TypeHelper();
//测试时使用
public static itypeheloper TypeHelper=new MockTypeHelper();
公共静态无效运行()
{
var validator=MockRepository.GenerateMock();
Expect(v=>v.Validate(Arg.Is.Equal(“输入”))).Return(true);
var method=TypeHelper.GetMethod(validator.GetType(),“Validate”);
var result=(bool)method.Invoke(验证器,新对象[]{“输入”});
控制台写入线(结果);
控制台。写入线(“完成”);
Console.ReadLine();
}
}
公共接口IValidator
{
bool验证(T-obj);
}
公共接口ITypeHelper
{
MethodInfo GetMethod(键入self,字符串名称);
}
公共类TypeHelper:ITypeHelper
{
公共虚拟方法信息GetMethod(键入self,字符串名称)
{
返回self.GetMethod(名称);
}
}
公共类MockTypeHelper:ITypeHelper
{
公共虚拟方法信息GetMethod(键入self,字符串名称)
{
if(typeof(IMockedObject).IsAssignableFrom(self)和&self.BaseType==typeof(object))
{
self=self.GetInterfaces()
.First(x=>x!=typeof(IMockedObject)和&x!=typeof(ISerializable)和&x!=typeof(IProxyTargetAccessor));
}
返回self.GetMethod(名称);
}
}

希望我越来越暖和;p

似乎RihnoMocks或Castle DynamicProxy已经改变了内部工作方式。正如@sQuir3l所指出的,它似乎在内部使用动态对象

在这种特殊情况下,您可以通过如下方式访问底层接口类型来解决更改:

var method = ((IMockedObject)validator).ImplementedTypes
    .Single(type => type == typeof(IValidator<string>))
    .GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
var方法=((IMockedObject)验证器)。实现的类型
.Single(type=>type==typeof(IValidator))
.GetMethod(“验证”,BindingFlags.Public | BindingFlags.Instance);

如果界面中没有
Result
方法,您如何期望使用
Result
方法创建模拟?它似乎与RhinoMocks的新版本无关。很好的catch@tzachs,这是我简化时的一个复制/粘贴错误。更正。为什么你首先需要反思?为什么不能直接调用
验证程序。验证
?与泛型有关吗?听起来你可能可以设计一个更好的解决方案。@tzachs我提供的示例非常简单,可以用来解决手头的问题。总体解决方案具有高度通用性,并且非常复杂,需要进行反射才能运行。值得一提的是,该解决方案确实有效,但测试工具似乎不再像以前版本的RhinoMocks那样运行。在我提供的简化示例中,根据消费者的实现情况,您的答案可能是正确的。然而,在我所处理的使用者的实际实现中,我不能访问泛型参数t(也不应该),只有它的类型信息。不幸的是,您的答案不能满足根本问题,即无法反映Rhino/Castle生成的代理对象。如果我没有弄错的话,您最近的编辑看起来像是在测试MockTypeHelper与使用者的交互,而不是与使用者验证验证程序的调用状态。当前执行代码的迭代是简洁和功能性的,纯粹为了测试而添加这样的工具似乎是不合适的。如果说有什么需要的话,那么创建一个明确的非模拟验证器类来进行测试将是更好的选择。我一直在寻找的是如何设置Rhinomock,以创建与上一个次要版本中默认的相同或类似的代理交互。问题在于,它最终修改代码以知道它正在测试中。例如,只有在进行测试时才会采取特殊措施,并且本质上只会验证测试线束。这些东西通常被认为是代码气味。Rhinomock很有可能在
var method = typeof(IValidator<T>).GetType()
    .GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);
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);
    }
}
var method = ((IMockedObject)validator).ImplementedTypes
    .Single(type => type == typeof(IValidator<string>))
    .GetMethod("Validate", BindingFlags.Public | BindingFlags.Instance);