Hi,
We just discovered some really weird behavior when mocking a class. It took us some time to figure out what went wrong and as it turned out it is not really an issue with TypeMock. However, based on this we would like to suggest a TypeMock feature that would be a help in situations like this.
We have an inheritance hierarchy in which one of the base classes implements both a finalizer and the IDisposable interface (The bases classes are Windows GUI components). Subclassed from these are some 3rd party GUI components which in turn are used as base classes for some of our own GUI components.
Unfortunately, the 3rd party GUI classes do not consistently implement Dispose(bool) as they should. In one particular case they do not check the disposing flag and they don’t do any null guarding either. I.e. if the type is not fully constructed calling Dispose on it will result in a NullReferenceException being thrown.
As we mock one of these GUI components (including the constructor) the 3rd party Dispose will fail as it violates the required semantics for a Dispose-method.
In order to get around this we can mock Dispose on the mocked object. However, that will not do the trick, because although it will mock the explicit call to Dispose it can’t handle the implicit call caused when the finalizer of the base class runs. Of course we could mock Dispose twice, but since the second time only happens during finalization that prevents us from using MockManager.Verify() in our test method.
We have identified two ways to get around this. Either call GC.SuppressFinalize on the mocked instance or attach a delegate to MockMethodCalled and call SuppressFinalize if CalledMethodName equals “Dispose”.
The feature suggestion is to have a ExpectDisposeAndSuppressFinalize method which in addition to setting up an ExpectCall to Dispose on the mocked type would ensure that SupressFinalize is called in order to remove the mocked type from the finalization queue (and hence preventing another call to Dispose).
We are perfectly aware that this is not an issue with TypeMock but we have seen several examples of implementations of Dispose which do not adhere to the IDisposable pattern as described by Microsoft. We are reluctant to report this as a bug to the developers of the 3rd party GUI components, due to the fact that the problem is only seen because we use mocking. Even if we did report this our guess is that we may see similar problems with other types and hence it would be really nice to be able to control this aspect as well when mocking a type.
The code below is a simplified illustration of the problem:
public class MyComponent : MyComponentBase {
}
public class MyComponentBase : Form {
Component c;
public MyComponentBase() {
c = new Component();
}
protected override void Dispose(bool disposing) {
// The disposing flag is ignored and there's no null guard so this
// will throw a NullReferenceException if the constructor didn't run
c.Dispose();
base.Dispose(disposing);
}
}
[TestMethod]
public void TestMethod() {
Mock MyMock = MockManager.Mock(typeof(MyComponent), Constructor.Mocked);
// This will handle the explicit call to Dispose (from "using"):
MyMock.ExpectCall("Dispose");
// Without this Dispose is called again during finalization:
System.GC.SuppressFinalize(MyMock.MockedInstance);
using (MyComponent m = new MyComponent()) {
}
MockManager.Verify();
}
To see the problem remove the call to SuppressFinalize in the test method.
Regards,
Brian