У меня есть следующий класс, который является декоратором для 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();
}
}
Я могу легко протестировать это innerDisposable
расположен когда Dispose()
назван:
[Test]
public void Dispose__DisposesInnerDisposable()
{
var mockInnerDisposable = new Mock<IDisposable>();
new DisposableDecorator(mockInnerDisposable.Object).Dispose();
mockInnerDisposable.Verify(x => x.Dispose());
}
Но как я пишу тест для проверки 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());
}
Возможно, я неправильно понял, но:
GC.WaitForPendingFinalizers();
Может помочь - http://msdn.microsoft.com/en-us/library/system.gc.waitforpendingfinalizers. aspx
При написании модульных тестов вы всегда должны пытаться тестировать внешнее видимое поведение, а не детали реализации. Кто-то может возразить, что подавление финализации действительно находится за пределами видимого поведения, но с другой стороны, вероятно, вы не можете (и не должны) издеваться над сборщиком мусора.
В вашем случае вы пытаетесь убедиться, что соблюдаются «лучшие практики» или практика кодирования. Его следует применять с помощью специального инструмента, такого как FxCop .