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的项目中,也可以将这些类放在单独的项目中。如果将它们分开,则需要在AssemblyInfo.cs中添加[assembly:InternalsVisibleTo(“ UnitTestProject1”)]。并根据需要更改项目名称。
运行测试,我想避免执行OpenFile()操作,这就是为什么我在测试中重写方法的原因。现在,当我调用测试时,它仍然通过文件打开操作调用基本方法。
我做错了什么吗?
编辑2:
将虚拟方法的内部修饰符更改为public可解决调用基本方法而不是被覆盖的方法的问题。如果可能,我想避免在我的原始项目中将修饰符更改为public。为何在内部通过InternalsVisibleTo
授予访问权限时阻止内部覆盖的任何建议都将受到赞赏。
答案 0 :(得分:1)
要模拟内部类型,您需要使用InternalsVisibleTo
,以便Moq能够生成子类并适当地重写。有关详细信息,请参见moq user guide-搜索“模拟内部类型”。基本上,您需要添加以下内容:
[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]
...但也可能具有公共密钥。
到那时,它应该可以正常工作,因为您的MethodToBeTested
是非虚拟的。如果您将MethodToBeTested
更改为虚拟的,则需要告诉Moq调用尚未通过模拟设置的任何方法:
Mock<Foo> mock = new Mock<Foo>(param) { CallBase = true };
那样,当您调用CallSomeMethod
时,它将执行常规方法,并且仅对ReturnMethod
使用模拟方法。