无论如何调用最小起订量基本方法的内部覆盖

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的模拟方法。