Это обсуждалось несколько раз раньше, но достоинства в приведенных ниже примерах не очевидны, поэтому, пожалуйста, несите меня.C# Unit Test - для издевки, заглушки или использования явной реализации
Я пытаюсь решить, использовать ли макетные реализации в своих модульных тестах и не определился с приведенными ниже двумя примерами: первый с использованием NSubstitute для издевательств, а второй с использованием разрешенной реализации SimpleInjector (Bootstrapper object).
По сути, оба тестируют одно и то же, что для объекта Disposed установлено значение true при вызове метода .Dispose() (см. Реализацию метода в нижней части этого сообщения).
На мой взгляд, второй метод имеет большее значение для регрессионного тестирования, поскольку прокси-модуль mock явно устанавливает для параметра Disposed значение true в первом примере, тогда как он задается фактическим методом .Dispose() в внедренной реализации ,
Почему вы предлагаете выбрать один из них для проверки того, что метод ведет себя так, как ожидалось? То есть что вызывается метод .Dispose() и что этот элемент установлен правильно.
[Test]
public void Mock_socket_base_dispose_call_is_received()
{
var socketBase = Substitute.For<ISocketBase>();
socketBase.Disposed.Should().BeFalse("this is the default disposed state.");
socketBase.Dispose();
socketBase.Received(1).Dispose();
socketBase.Disposed.Returns(true);
socketBase.Disposed.Should().BeTrue("the ISafeDisposable interface requires this.");
}
[Test]
public void Socket_base_is_marked_as_disposed()
{
var socketBase = Bootstrapper.GetInstance<ISocketBase>();
socketBase.Disposed.Should().BeFalse("this is the default disposed state.");
socketBase.Dispose();
socketBase.Disposed.Should().BeTrue("the ISafeDisposable interface requires this.");
}
Для справки метод .Dispose() просто так:
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposeAndFinalize"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected void Dispose(bool disposeAndFinalize)
{
if (Disposed)
{
return;
}
if (disposeAndFinalize)
{
DisposeManagedResources();
}
DisposeUnmanagedResources();
Disposed = true;
}
Приветствия
Я говорю, чтобы ваши тесты были максимально простыми. Макет, только если тест достаточно сложный, чтобы потребовать его, ИМХО. Если вы используете VS2012, попробуйте использовать [подделки] (http://msdn.microsoft.com/en-us/library/hh549175.aspx). В вашем случае здесь я не вижу ничего плохого в вашем втором подходе (я не пробовал ваш код, но он выглядит хорошо) –
@GabeThorns: Но если тест «достаточно сложный», может быть, проблема может быть связана с тест (или тестируемый класс) :-) – Steven
Я согласен с @Steven Тесты не должны быть «сложными», поскольку это имеет тенденцию сигнализировать о запахе кода – McDonnellDean