我如何使用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调用检查方法是否已被调用。