如何对终结器进行单元测试?

Gra*_*meF 19 .net c# unit-testing idisposable finalizer

我有以下类,它是一个IDisposable对象的装饰器(我省略了它添加的东西),它本身IDisposable使用一个通用模式实现:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以很容易地测试innerDisposable时被布置Dispose()叫做:

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

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

    mockInnerDisposable.Verify(x => x.Dispose());
}
Run Code Online (Sandbox Code Playgroud)

但我怎么写一个测试,以确保innerDisposable不会得到安置被终结?我想写这样的东西,但它失败了,大概是因为GC线程没有调用终结器:

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

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

    mockInnerDisposable.Verify(x => x.Dispose(), Times.Never());
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*lph 8

编写单元测试时,应始终尝试测试外部可见行为,而不是实现细节.有人可能会说,压制最终确定确实是在可见行为之外,但另一方面,你可能也不可能(也不应该)嘲笑这个收集者.

在您的案例中,您尝试确保的是遵循"最佳实践"或编码实践.它应该通过为此目的而制作的工具强制执行,例如FxCop.

  • 我实际上有一个bug,因为我忘了检查`Dispose()`中的`disposing`标志,所以想在我修复它之前添加一个测试. (10认同)