我如何使用 Moq 测试 C# 终结器中的两个方法是否已在 GC 上调用?

How can I use Moq to test that two methods inside a C# finalizer have been called on GC?

我正在尝试编写一个单元测试,以确保已调用终结器中的两个方法。我的问题是我无法断言超出范围的模拟。让我用代码展示我的问题:

internal class MyClass
{
    MyClass() { }

    ~MyClass()
    {
        this.MethodA()
        this.MethodB()
    }
}

[TestMethod]
public void Finalize_NormalDestruction_MethodAandMethodBCalled()
{
    var myMock = new myMock();

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Assert.IsTrue(myMock.IsMethodACalled);  // Fails, myMock never went OOS
    Assert.IsTrue(myMock.IsMethodBCalled);  // Fails, myMock never went OOS
}

[TestMethod]
public void Finalize_NormalDestruction_MethodAandMethodBCalled()
{
    {
        var myMock = new myMock();
    }

    GC.Collect();
    GC.WaitForPendingFinalizers();

    Assert.IsTrue(myMock.IsMethodACalled);  // Doesn't compile, myMock is OOS
    Assert.IsTrue(myMock.IsMethodBCalled);  // Doesn't compile, myMock is OOS
}

有没有一种方法可以使用 Moq 来测试终结器是否具有 运行?我已经能够使用断点手动测试它,但我想要一个自动化测试。

为了使终结器 运行 您的代码不能有任何对该实例的实时引用。如果您真的想在测试中验证这一点,您有两种选择。

您可以存储方法具有 运行 作为该类型的静态成员这一事实。但是,您必须做任何必要的簿记,以确保它 运行 适合您感兴趣的实例。

或者,您可以让终结器复活实例。不过,我不建议仅仅为了测试而这样做。