首页 / C# / C#单元测试-模拟,存根或使用显式实现
C#单元测试-模拟,存根或使用显式实现
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#单元测试-模拟,存根或使用显式实现,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3518字,纯文字阅读大概需要6分钟。
内容图文
![C#单元测试-模拟,存根或使用显式实现](/upload/InfoBanner/zyjiaocheng/677/2baf429a669e41ed9aa8d0c1fcecb746.jpg)
之前已经对此进行了多次讨论,但是以下示例中的优点并不明显,因此请耐心等待.
我正在尝试确定是否在单元测试中使用模拟实现,并且给出以下两个示例,我不确定,第一个使用NSubstitute进行模拟,第二个使用SimpleInjector(Bootstrapper对象)解决的实现.
本质上,两者都在测试同一件事,即当调用.Dispose()方法时,将Disposed成员设置为true(请参阅本文底部的method的实现).
在我看来,第二种方法对于回归测试更有意义,因为模拟代理在第一个示例中将Disposed成员显式设置为true,而由注入的实现中的实际.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;
}
干杯
解决方法:
这两种测试方法对我来说似乎都很奇怪.使用第一种方法,您似乎没有测试任何东西(或者我可能会误解NSubstitute所做的事情),因为您只是在模拟ISocketBase接口(没有要测试的行为)并开始测试该模拟对象,而不是真正的实现. .
第二种方法也是不好的,因为您不应在单元测试中使用任何DI容器.这只会使事情变得更复杂,因为:
>现在,您使用所有测试都使用的共享状态,这会使所有测试相互依赖(测试应独立运行).
>容器引导逻辑将变得非常复杂,因为您想为不同的测试插入不同的模拟,并且再次,在测试之间不共享任何对象.
>您的测试对根本不存在的框架或外观有额外的依赖.从这个意义上讲,您只是在使测试变得更加复杂.它可能会稍微复杂一点,但是仍然是一个额外的复杂性.
相反,您应该做的是始终在单元测试(或测试工厂方法)本身内部创建被测类(SUT).您可能仍想使用模拟框架创建SUT依赖关系,但这是可选的.因此,IMO测试应如下所示:
[Test]
public void A_nondisposed_Socket_base_should_not_be_marked_dispose()
{
// Arrange
Socket socket = CreateValidSocket();
// Assert
socketBase.Disposed.Should().BeFalse(
"A non-disposed socket should not be flagged.");
}
[Test]
public void Socket_base_is_marked_as_disposed_after_calling_dispose()
{
// Arrange
Socket socket = CreateValidSocket();
// Act
socketBase.Dispose();
// Assert
socketBase.Disposed.Should().BeTrue(
"Should be flagged as Disposed.");
}
private static Socket CreateValidSocket()
{
return new Socket(
new FakeDependency1(), new FakeDependency2());
}
请注意,我将您的单个测试分为2个测试.在调用dispose之前Dispose应该为false并不是该测试运行的前提;这是系统正常运行的要求.换句话说,您需要对此进行明确说明,并需要进行第二次测试.
还要注意使用CreateValidSocket工厂方法,该方法可在多个测试中重复使用.当其他测试检查类的其他部分需要更具体的伪造或模拟对象时,此方法可能会有多个重载(或可选参数).
内容总结
以上是互联网集市为您收集整理的C#单元测试-模拟,存根或使用显式实现全部内容,希望文章能够帮你解决C#单元测试-模拟,存根或使用显式实现所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。