【发布时间】:2013-04-17 10:40:30
【问题描述】:
这个问题之前已经讨论过很多次了,但是下面例子中的优点并不明显,所以请多多包涵。
我正在尝试决定是否在我的单元测试中使用模拟实现,但鉴于以下两个示例,我尚未决定,第一个使用 NSubstitute 进行模拟,第二个使用 SimpleInjector(Bootstrapper 对象)解析的实现。
基本上两者都在测试同一件事,即在调用 .Dispose() 方法时将 Disposed 成员设置为 true(请参阅本文底部的方法实现)。
在我看来,第二种方法对回归测试更有意义,因为模拟代理在第一个示例中显式地将 Disposed 成员设置为 true,而在注入的实现中它是由实际的 .Dispose() 方法设置的。
您为什么建议我选择一个而不是另一个来验证该方法的行为是否符合预期? IE。 .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。在您的情况下,我认为您的第二种方法没有任何问题(我没有尝试过您的代码,但看起来不错)
-
@GabeThorns:但是如果测试“足够复杂”,则测试(或被测类)可能已经存在问题:-)
-
我同意@Steven 测试不应该真的很“复杂”,因为这往往表明代码有异味
标签: c# unit-testing mocking simple-injector nsubstitute