Dmy*_*iak 5 .net unit-testing idisposable finalizer
问题是,如何在调用finalize时测试对象配置资源的事实。该类的代码:
public class TestClass : IDisposable {
public bool HasBeenDisposed {get; private set; }
public void Dispose() {
HasBeenDisposed = true;
}
~TestClass() {
Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我现在不关心正确的Dispose / Finalize实现,因为我想首先找到对其进行测试的方法。在此阶段,如果调用了Dispose / Finalize软件,就可以假设将HasBeenDisposed设置为true。
我写的实际测试看起来像:用
WEAKREFERENCE更新:
[Test]
public void IsCleanedUpOnGarbadgeCollection() {
var o = new TestClass();
o.HasBeenDisposed.Should().Be.False();
**var weak = new WeakReference(o, true); // true =Track after finalisation
o = null; // Make eligible for GC**
GC.Collect(0, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
**((TestClass)weak.Target)**.HasBeenDisposed.Should().Be.True();
}
Run Code Online (Sandbox Code Playgroud)
或我更喜欢的代码(ADDED AFTER UPDATE):
[Test]
public void IsCleanedUpOnGarbadgeCollection() {
WeakReference weak = null;
// Use action to isolate instance and make them eligible for GC
// Use WeakReference to track the object after finalisaiton
Action act = () = {
var o = new TestClass();
o.HasBeenDisposed.Should().Be.False();
weak = new WeakReference(o, true); // True=Track reference AFTER Finalize
};
act();
GC.Collect(0, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
// No access to o variable here which forces us to use WeakReference only to avoid error
((TestClass)weak.Target).HasBeenDisposed.Should().Be.True();
}
Run Code Online (Sandbox Code Playgroud)
此测试失败(通过后更新),但我观察到以下(UPDATED):
那么正确的测试方法是什么。我想念什么?
我想是变量o阻止了GC收集它。
更新:是的,这是问题。不得不改用WeakReference。
“我想是变量 o 阻止了 GC 收集它。” 正确的。堆栈上存在引用意味着该对象是可访问的,因此不符合收集(和终结)的条件。
由于对象只有在没有引用时才会被终结,因此测试终结行为可能会很棘手。(您需要引用该对象才能对其进行断言!)一种方法是间接执行此操作:让对象在终结期间发送某种消息。但这纯粹出于测试目的而扭曲了最终代码。您还可以保留对该对象的弱引用,这将使其有资格进行终结,并让它在终结器中自行复活 - 但同样,您不希望让它在生产代码中自行复活。
| 归档时间: |
|
| 查看次数: |
1504 次 |
| 最近记录: |