我试图在我的代码重载签名中测试(使用Moq)重载的受保护泛型方法:
protected void AutoMap<FromType, ToType>(IList<FromType> sources
, IList<ToType> destinations)
和
protected void AutoMap<FromType, ToType>(FromType from
, ToType to)
为了能够访问这些方法中的第二个,我使用的是PrivateObject,然后通过反射调用方法:
a obj_a = new a();
b obj_b = new b();
PrivateObject o = new PrivateObject(controller);
o.Invoke("AutoMap"
, new Type[] { typeof(a), typeof(b) }
, new Object[] { obj_a, obj_b }
, new Type[] { typeof(a), typeof(b) });
当我运行测试时,我得到System.Reflection.AmbiguousMatchException,表示发现了不明确的匹配。
任何人都可以告诉我如何正确地做到这一点? 干杯 ķ。
答案 0 :(得分:2)
通常,您不应该测试受保护的方法。只应测试公共方法。从单元测试的角度来看,受保护的方法应该被视为私有。
您应该测试您的实现类,并看到它按预期工作。如果这个类使用受保护/私有方法来完成它的工作 - 这是实现细节,并且实现可以随时改变而不改变类的行为(想想重构)。
假设你有:
public abstract class Base
{
public virtual int GetResult(int data)
{
var z = GetMoreData();
return data*z;
}
protected int GetMoreData()
{
///something
return something;
}
}
public class MyRealImplementation : Base
{
public override int GetResult(int data)
{
//wahtever
}
}
没有办法(或没有意义)测试受保护的方法。我们不知道被覆盖的GetResult会使用它(它可能会,也可能不会)。
唯一想测试的是GetResult是否返回预期结果,而不是它是如何做到的。
在特定情况下,如果你在接口后面抽象映射功能会更好,所以你可以模拟它。
public interface IMapper
{
AutoMap<FromType, ToType>(IList<FromType> sources, IList<ToType> destinations);
oid AutoMap<FromType, ToType>(FromType from, ToType to);
}
在您的PrivateObject中注入该接口并使用它而不是受保护的方法。有了这个,你会:
一般情况下 - 每次编写单元测试都很困难,通常这意味着类/方法做得太多。
答案 1 :(得分:1)
虽然我同意Sunny的answer关于测试受保护方法的愚蠢行为,但这个问题让我很感兴趣,所以我试着搞清楚这里出了什么问题。
问题是PrivateObject类的限制,它基本上只是一些反射方法的包装器。这是一个已知限制,请参阅示例问题here和here。
如果你真的想测试这样的方法,你需要自己使用这些反射方法。
//this is ugly, but the quickest way I could filter down to the overload that
//doesn't take in the IList interface arguments
var method = typeof (YOUR_CONTROLLER_CLASS).GetMethods(
BindingFlags.Instance | BindingFlags.NonPublic)
.First(m => m.IsGenericMethod
&& m.Name == "AutoMap"
&& !m.GetParameters()[0].ParameterType.IsInterface);
var genericMethod = method.MakeGenericMethod(new[] {typeof (a), typeof (b)});
genericMethod.Invoke(controller, new object[]{ obj_a, obj_b });
希望有所帮助。