在Moq中模拟受保护的虚拟(非泛型)方法很简单:
public class MyClass
{
....
protected virtual int MyMethod(Data data){..}
}
并嘲笑它:
myMock.Protected().Setup<int>("MyMethod", ItExpr.Is<Data>( ...
如果受保护的方法是通用的,我无法找到使用相同技术的方法,例如:
protected virtual int MyMethod<T>(T data)
除了使用包装类来覆盖该方法之外,任何想法都是如此,非常感谢。
答案 0 :(得分:6)
我检查了源代码,似乎不支持使用Moq模拟受保护的泛型方法:
Protected()
方法创建一个类ProtectedMock<T>
的实例,它使用以下方法获取您要模拟的方法:
private static MethodInfo GetMethod(string methodName, params object[] args)
{
return typeof(T).GetMethod(
methodName,
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
null,
ToArgTypes(args),
null);
}
它使用Type.GetMethod来获取模拟方法,但是GetMethod
(尽管MSDN状态不同)与泛型不匹配,请参阅:
Get a generic method without using GetMethods
旁注: 在我看来,嘲笑一个受保护的成员是一种代码味道,我宁愿尝试通过重构我的设计来避免它(除了它在Moq中不支持)。
答案 1 :(得分:0)
自Moq 4.13(2019-09-01)起可以通过对受保护方法使用As
和对泛型类型参数使用It.IsAnyType
来完成:
classUnderTest.Protected().As<IMyMethodMock>().Setup(x => x.MyMethod(It.IsAny<It.IsAnyType>())).Returns(...);
并为模拟方法创建以下接口:
public interface IMyMethodMock
{
int MyMethod<T>(T data);
}
完整示例:
[TestClass]
public class MockingProtectedGenericFixture
{
[TestMethod]
public void test()
{
// Arrange
var classUnderTest = new Mock<MyClass>();
classUnderTest.Protected().As<IMyMethodMock>().Setup(x => x.MyMethod(It.IsAny<It.IsAnyType>())).Returns(2);
// Act
var resForStringData = classUnderTest.Object.GetNumber("DataString");
var resForBooleanData = classUnderTest.Object.GetNumber(true);
// Assert
Assert.AreEqual(2, resForStringData);
Assert.AreEqual(2, resForBooleanData);
}
}
public class MyClass
{
public int GetNumber<T>(T data)
{
return MyMethod(data);
}
protected virtual int MyMethod<T>(T data)
{
return 1;
}
}
public interface IMyMethodMock
{
int MyMethod<T>(T data);
}