Should Dispose methods be unit tested?

sbenderli picture sbenderli · Jul 15, 2010 · Viewed 15k times · Source

I am using C#. Is it advised to unit test dispose methods? If so why, and how should one test these methods?

Answer

Igor Zevaka picture Igor Zevaka · Jul 16, 2010

Yes, but it might be hard. There are two things that can generally happen in Dispose implementation:

Unmanaged resources are released.

In this case it's pretty hard to verify that the code called, for example, Marshal.Release. A possible solution is to inject an object that can do the disposing and pass a mock to it during testing. Something to this effect:

interface ComObjectReleaser {
    public virtual Release (IntPtr obj) {
       Marshal.Release(obj);
    }
}

class ClassWithComObject : IDisposable {

    public ClassWithComObject (ComObjectReleaser releaser) {
       m_releaser = releaser;
    }

    // Create an int object
    ComObjectReleaser m_releaser;
    int obj = 1;
    IntPtr m_pointer = Marshal.GetIUnknownForObject(obj);

    public void Dispose() {
      m_releaser.Release(m_pointer);
    }
}

//Using MOQ - the best mocking framework :)))
class ClassWithComObjectTest {

    public DisposeShouldReleaseComObject() {
       var releaserMock = new Mock<ComObjectReleaser>();
       var target = new ClassWithComObject(releaserMock);
       target.Dispose();
       releaserMock.Verify(r=>r.Dispose());
    }
}

Other classes' Dispose method is called

The solution to this might not be as simple as above. In most cases, implementation of Dispose is not virtual, so mocking it is hard.

One way is to wrap up those other objects in a mockable wrapper, similar to what System.Web.Abstractions namespace does for HttpContext class - i.e. defines HttpContextBase class with all virtual methods that simply delegates method calls to the real HttpContext class.

For more ideas on how to do something like that have a look at System.IO.Abstractions project.