此之前已經討論了很多次,但在下面的示例中的優點並不明顯,所以請多多包涵。C#單元測試 - 嘲笑,存根或使用顯式實現
我想決定是否在我的單元測試中使用模擬實現,並未定,給出以下兩個示例,第一個使用NSubstitute進行嘲諷,第二個使用SimpleInjector(Bootstrapper對象)解析實現。
本質上都被檢測爲同一件事,即設置構件設置爲true時.Dispose()方法被調用(請參閱本崗位的底部實現方法)。
爲了我的眼睛,該第二方法使得對迴歸測試更有意義的模擬代理顯式地設定設置構件在第一示例中是真實的,而它是由實際.Dispose()方法在注射的執行設定。
爲什麼你會建議我選擇了另一種用於驗證方法的行爲如預期?即調用.Dispose()方法,並通過此方法正確設置Disposed成員。
[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,請嘗試利用[fakes](http://msdn.microsoft.com/zh-cn/library/hh549175.aspx)。在你的情況下,我沒有看到你的第二種方法有什麼問題(我沒有嘗試過你的代碼,但看起來不錯) –
@GabeThorns:但是如果測試「夠複雜」,可能已經有問題了測試(或測試中的類別):-) – Steven
我同意@Steven測試不應該是「複雜」的,因爲這往往表示代碼味道 – McDonnellDean