How do I unit test a finalizer?

GraemeF picture GraemeF · May 24, 2010 · Viewed 7.7k times · Source

I have the following class which is a decorator for an IDisposable object (I have omitted the stuff it adds) which itself implements IDisposable using a common pattern:

public class DisposableDecorator : IDisposable
{
    private readonly IDisposable _innerDisposable;

    public DisposableDecorator(IDisposable innerDisposable)
    {
        _innerDisposable = innerDisposable;
    }

    #region IDisposable Members

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    #endregion

    ~DisposableDecorator()
    {
        Dispose(false);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
            _innerDisposable.Dispose();
    }
}

I can easily test that innerDisposable is disposed when Dispose() is called:

[Test]
public void Dispose__DisposesInnerDisposable()
{
    var mockInnerDisposable = new Mock<IDisposable>();

    new DisposableDecorator(mockInnerDisposable.Object).Dispose();

    mockInnerDisposable.Verify(x => x.Dispose());
}

But how do I write a test to make sure innerDisposable does not get disposed by the finalizer? I want to write something like this but it fails, presumably because the finalizer hasn't been called by the GC thread:

[Test]
public void Finalizer__DoesNotDisposeInnerDisposable()
{
    var mockInnerDisposable = new Mock<IDisposable>();

    new DisposableDecorator(mockInnerDisposable.Object);
    GC.Collect();

    mockInnerDisposable.Verify(x => x.Dispose(), Times.Never());
}

Answer

Steven Robbins picture Steven Robbins · May 24, 2010

I might be misunderstanding, but:

GC.WaitForPendingFinalizers();

Might do the trick - http://msdn.microsoft.com/en-us/library/system.gc.waitforpendingfinalizers.aspx