使用MOQ基本方法进行内部覆盖将被调用

时间:2018-07-12 13:07:40

标签: c# nunit moq

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授予访问权限时阻止内部覆盖的任何建议都将受到赞赏。

1 个答案:

答案 0 :(得分:1)

要模拟内部类型,您需要使用InternalsVisibleTo,以便Moq能够生成子类并适当地重写。有关详细信息,请参见moq user guide-搜索“模拟内部类型”。基本上,您需要添加以下内容:

[assembly:InternalsVisibleTo("DynamicProxyGenAssembly2")]

...但也可能具有公共密钥。

到那时,它应该可以正常工作,因为您的MethodToBeTested是非虚拟的。如果您将MethodToBeTested更改为虚拟的,则需要告诉Moq调用尚未通过模拟设置的任何方法:

Mock<Foo> mock = new Mock<Foo>(param) { CallBase = true };

那样,当您调用CallSomeMethod时,它将执行常规方法,并且仅对ReturnMethod使用模拟方法。