无论如何调用最小起订量基本方法的内部覆盖
Internal Override with MOQ base method gets called regardless
public class StuffToTest
{
//do something..
internal string MethodToBeTested()
{
//do something..
string result = MethodWithFileOpenAction(new List<string>(), new List<string>());
return result;
}
internal virtual string MethodWithFileOpenAction(List<string> text1, List<string> text2)
{
string text = OpenFile();
//do something..
return text;
}
internal string OpenFile()
{
return "Example string base Method";
}
}
[TestFixture]
public class TestClass
{
[Test]
public void TestMethod()
{
string input = "Example string not base Method";
Mock<StuffToTest> mockedObject = new Mock<StuffToTest>();
mockedObject.Setup(item => item.MethodWithFileOpenAction(
It.IsAny<List<string>>(),
It.IsAny<List<string>>()))
.Returns(input);
//Added after answer was provided, problem still persists
mockedObject.CallBase = true;
string result = mockedObject.Object.MethodToBeTested();
Assert.AreEqual("Example string not base Method", result);
}
}
编辑:
要重现我的问题,您可以将两个 类 放在一个为 NUnit 创建 dll 的项目中,或者您可以将 类 放在单独的项目中。如果将它们分开,则需要将 [assembly: InternalsVisibleTo("UnitTestProject1")] 添加到 AssemblyInfo.cs。并根据需要更改项目名称。
运行 测试,我想避免 OpenFile() 操作,这就是为什么我重写了测试中的方法。现在我调用测试时,它仍然调用带有文件打开操作的基方法。
我做错了什么吗?
编辑 2:
将虚方法的内部修饰符更改为 public 修复了调用基方法而不是重写方法的问题。如果可能,我想避免在我的原始项目中将修饰符更改为 public。任何关于为什么在通过 InternalsVisibleTo
授予访问权限时内部阻止覆盖的建议将不胜感激。
要模拟内部类型,您需要使用 InternalsVisibleTo
以便 Moq 能够生成子类并适当地覆盖。有关详细信息,请参阅 moq user guide - 搜索 "mocking internal types"。基本上你需要添加如下内容:
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
...但也可能带有 public 键。
到那时,它应该可以正常工作,因为您的 MethodToBeTested
是非虚拟的。如果您将 MethodToBeTested
更改为虚拟的,则需要告诉 Moq 调用任何尚未设置为模拟的方法:
Mock<Foo> mock = new Mock<Foo>(param) { CallBase = true };
这样当你调用CallSomeMethod
时,它会执行常规方法,并且只使用ReturnMethod
的模拟方法。
public class StuffToTest
{
//do something..
internal string MethodToBeTested()
{
//do something..
string result = MethodWithFileOpenAction(new List<string>(), new List<string>());
return result;
}
internal virtual string MethodWithFileOpenAction(List<string> text1, List<string> text2)
{
string text = OpenFile();
//do something..
return text;
}
internal string OpenFile()
{
return "Example string base Method";
}
}
[TestFixture]
public class TestClass
{
[Test]
public void TestMethod()
{
string input = "Example string not base Method";
Mock<StuffToTest> mockedObject = new Mock<StuffToTest>();
mockedObject.Setup(item => item.MethodWithFileOpenAction(
It.IsAny<List<string>>(),
It.IsAny<List<string>>()))
.Returns(input);
//Added after answer was provided, problem still persists
mockedObject.CallBase = true;
string result = mockedObject.Object.MethodToBeTested();
Assert.AreEqual("Example string not base Method", result);
}
}
编辑: 要重现我的问题,您可以将两个 类 放在一个为 NUnit 创建 dll 的项目中,或者您可以将 类 放在单独的项目中。如果将它们分开,则需要将 [assembly: InternalsVisibleTo("UnitTestProject1")] 添加到 AssemblyInfo.cs。并根据需要更改项目名称。
运行 测试,我想避免 OpenFile() 操作,这就是为什么我重写了测试中的方法。现在我调用测试时,它仍然调用带有文件打开操作的基方法。
我做错了什么吗?
编辑 2:
将虚方法的内部修饰符更改为 public 修复了调用基方法而不是重写方法的问题。如果可能,我想避免在我的原始项目中将修饰符更改为 public。任何关于为什么在通过 InternalsVisibleTo
授予访问权限时内部阻止覆盖的建议将不胜感激。
要模拟内部类型,您需要使用 InternalsVisibleTo
以便 Moq 能够生成子类并适当地覆盖。有关详细信息,请参阅 moq user guide - 搜索 "mocking internal types"。基本上你需要添加如下内容:
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
...但也可能带有 public 键。
到那时,它应该可以正常工作,因为您的 MethodToBeTested
是非虚拟的。如果您将 MethodToBeTested
更改为虚拟的,则需要告诉 Moq 调用任何尚未设置为模拟的方法:
Mock<Foo> mock = new Mock<Foo>(param) { CallBase = true };
这样当你调用CallSomeMethod
时,它会执行常规方法,并且只使用ReturnMethod
的模拟方法。