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

我如何使用Moq测试一个C#finalizer中的两个方法是否已在GC上被调用?,c#,unit-testing,garbage-collection,moq,finalizer,C#,Unit Testing,Garbage Collection,Moq,Finalizer,我正在尝试编写一个单元测试,以确保在终结器中调用了两个方法。我的问题是,我不能对超出范围的模拟进行断言。让我来说明我的代码问题: internal class MyClass { MyClass() { } ~MyClass() { this.MethodA() this.MethodB() } } [TestMethod] public void Finalize_NormalDestruction_MethodAandMet

我正在尝试编写一个单元测试,以确保在终结器中调用了两个方法。我的问题是,我不能对超出范围的模拟进行断言。让我来说明我的代码问题:

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来测试终结器是否已经运行?我已经能够使用断点手动测试它,但是我想要一个自动测试。

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

您可以存储方法已作为该类型的静态成员运行的事实。但是,您必须自己做任何必要的簿记工作,这样才能确保它针对您感兴趣的实例运行


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

此类型应实现
IDisposable
,以允许显式处理,即使它也在终结器中处理这些对象。然后,您的自动化测试可以使用显式处理来确保清理所有必需的资源。实际上,您正试图编写一个自动测试,以表明GC在清理对象之前调用对象的终结器。首先,这实际上不是保证;对象永远不会被最终确定是完全正确的。其次,您的单元测试应该测试这个类,而不是GC。我完全同意我不想测试GC。在测试中使用blocks/use.Dispose()实现IDisposable并包装一些生产代码应该可以很好地工作——我不确定是否有其他方法可以使用Moq来测试它。我没有时间编写完整的示例并进行测试,但是我认为进行此测试的方法是使用,这样您就不必存储强引用,并且可以在终结器运行后将对象取回。我同意,让终结器恢复实例或存储在静态函数中运行的方法感觉不太好。目前,我所做的修复是让终结器调用类中的另一个方法。然后出于测试目的,我使用Moq的Verify调用检查方法是否已被调用。