The question is how can I test the fact that object disposes resources when finalise is called. The code for the class:
public class TestClass : IDisposable {
public bool HasBeenDisposed {get; private set; }
public void Dispose() {
HasBeenDisposed = true;
}
~TestClass() {
Dispose();
}
}
Please note that I don't care about the correct implementation of Dispose/Finalize just now as I want to find the way to test it first. At this stage it is enough to assume the HasBeenDisposed will be set to true if Dispose/Finalize ware called.
The actual test I wrote looks like:
UPDATED WITH 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();
}
or the code I like better (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();
}
This test fails (PASSES AFTER UPDATE) but I observe following (UPDATED):
- GC.WaitForPendingFinalizers() does suspend the thread and finalises instance in o, but only if is not rooted. Assigned NULL to it and used WeakReference to get it AFTER finalisation.
- Finilize (destructor) code is executed at correct point when the o does not hold the instance.
So what is the correct way of testing this. What do I miss?
I suppose it is the variable o that prevents GC from collection it.
UPDATE: Yes it is the issue. Had to use WeakReference instead.