我有一个类,它包含一个公共方法,它依赖于一个内部方法来正确返回其值。
让我们考虑以下类和测试文件:
public class ClassUnderTest
{
public string NotMockedPublicMethod()
{
return MockedMethod();
}
virtual public string MockedMethod()
{
return "original";
}
}
以下测试用例将起作用:
var mock = new Mock<ClassUnderTest> { CallBase = true };
mock.Setup(m => m.MockedMethod()).Returns("mocked");
Assert.AreEqual("mocked", mock.Object.NotMockedPublicMethod());
但假设我的MockedMethod()
在外部没有任何用处。问题是将此方法标记为internal
(即使正确使用InternalsVisibleTo()
):
virtual internal string MockedMethod()
将使与消息Assert.AreEqual failed. Expected:<mocked>. Actual:<original>
完全相同的测试失败。
这是一个Moq错误还是一些限制?
这不是一个bug或限制。在使方法内部化后(甚至在添加InternalsVisibleTo后),您的测试失败了,因为它不是在调用模拟方法,而是在调用实际方法。
您需要为DynamicProxyGenAssembly2以及以下Url添加InternalsVisibleTo。
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
http://www.blackwasp.co.uk/MoqInternals.aspx
Url没有提供正确的解释,但它是:
Moq使用Castle Project的DynamicProxy在运行时动态生成代理,这样就可以在不修改类代码的情况下拦截对象的成员。这就是Moq返回在"Setup()"中指定的值的方式。returns(在您的情况下为字符串"mocked")
动态代理Url:http://www.castleproject.org/projects/dynamicproxy/
我查看了DynamicProxy的源代码(请参阅下面的url),发现它使用"DynamicProxyGenAssembly2"作为生成的程序集的程序集名称,这就是为什么您还需要为DynamicProxyGenAssembly2添加InternalsVisibleTo。
public static readonly String DEFAULT_ASSEMBLY_NAME = "DynamicProxyGenAssembly2";
https://github.com/castleproject/Castle.DynamicProxy-READONLY/blob/ed8663b23a54bed641e5f97e39a6bc16fe0d976f/src/Castle.DynamicProxy/ModuleScope.cs