如何在单个测试中同时执行多个断言

前言

虽然,推荐做法是每次测试只断言一件事,但是,在实际工作中,我们可能需要对同一个对象同时执行多个断言。

例如,微软官方示例项目eShopOnContainers有一个测试用例的实现代码如下:

[Fact]
public async Task Add_to_cart_success()
{//Arrangevar fakeCatalogItem = GetFakeCatalogItem();_basketServiceMock.Setup(x => x.AddItemToBasket(It.IsAny<ApplicationUser>(), It.IsAny<Int32>())).Returns(Task.FromResult(1));//Actvar orderController = new CartController(_basketServiceMock.Object, _catalogServiceMock.Object, _identityParserMock.Object);orderController.ControllerContext.HttpContext = _contextMock.Object;var actionResult = await orderController.AddToCart(fakeCatalogItem);//AssertAssert.Equal("Catalog", redirectToActionResult.ControllerName);Assert.Equal("Index", redirectToActionResult.ActionName);
}

如果我们将所有断言都改成必定失败:

//Assert
Assert.Equal("WrongCatalog", redirectToActionResult.ControllerName);
Assert.Equal("WrongIndex", redirectToActionResult.ActionName);

但运行测试时,只会提示第一个失败的断言:

70767309db00afc6a01cd950d0017030.png

在这种情况下,一个个断言去验证并修正比较耗时。

如果同时能够看到所有失败的断言则更加有帮助。

手工实现

查看`Assert.Equal`的实现代码[1],它是通过抛出EqualException异常来表明断言失败:

public static void Equal<T>(T expected, T actual, IEqualityComparer<T> comparer)
{GuardArgumentNotNull(nameof(comparer), comparer);var expectedAsIEnum = expected as IEnumerable;var actualAsIEnum = actual as IEnumerable;// If both are IEnumerable (or null), see if we got an AssertEqualityComparer<T>, so that// we can invoke it to get the mismatched index.if ((expectedAsIEnum != null && (actual == null || actualAsIEnum != null)) ||(actualAsIEnum != null && expected == null)){var aec = comparer as AssertEqualityComparer<T>;int? mismatchedIndex;if (aec != null && !aec.Equals(expected, actual, out mismatchedIndex)){if (mismatchedIndex.HasValue)throw EqualException.FromEnumerable(expectedAsIEnum, actualAsIEnum, mismatchedIndex.Value);elsethrow new EqualException(expected, actual);}}if (!comparer.Equals(expected, actual))throw new EqualException(expected, actual);
}

而所有断言异常都继承自基类XunitException

89b3bacad82d4b4949db8f645f5f23b2.png

74c815aa5aa137fe83890c7080be8b99.png

因此,我们可以捕获每个断言的异常,然后将多个异常添加到集合中,在测试结束时再抛出:

var xunitExceptions = new List<XunitException>();
try
{Assert.Equal("WrongCatalog", redirectToActionResult.ControllerName);
}
catch (XunitException ex)
{xunitExceptions.Add(ex);
}try
{Assert.Equal("WrongIndex", redirectToActionResult.ActionName);
}
catch (XunitException ex)
{xunitExceptions.Add(ex);
}if (xunitExceptions.Any())
{throw new AggregateException(xunitExceptions.ToArray());
}

7124bcb9edfbf35043d3c9f77529b3ba.png

这里虽然列出了所有失败断言,但是所有错误显示了2遍,而且我们必须为测试编写大量的try-catch代码。

有不有更好的方法呢?!

FluentAssertions

FluentAssertions是一组.NET扩展方法,允许用更自然的语法去验证断言。

引用Nuget包FluentAssertions,示例的断言可以修改成如下格式:

redirectToActionResult.ControllerName.Should().Be("WrongCatalog");
redirectToActionResult.ActionName.Should().Be("WrongIndex");

除此之外,还可以将多个断言放到一个AssertionScope中,以便FluentAssertions在所有失败的范围末尾抛出一个异常:

using (new FluentAssertions.Execution.AssertionScope())
{redirectToActionResult.ControllerName.Should().Be("WrongCatalog");redirectToActionResult.ActionName.Should().Be("WrongIndex");
}

b0bf3d0f7bb8dabde37e1c933dbd20a4.png

结论

有时,将多个断言组合在一起测试是有意义的。

在这种情况下,可以使用FluentAssertions的AssertionScope来编写此类测试。

如果你觉得这篇文章对你有所启发,请关注我的个人公众号”My IO“

参考资料

[1]

Assert.Equal的实现代码: https://github.com/xunit/assert.xunit/blob/main/EqualityAsserts.cs#L78

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/293458.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用ArcGIS Server发布我们的数据

原文:使用ArcGIS Server发布我们的数据引言 上一篇我们已经安装好了ArcGIS体系的服务软件&#xff0c;这一篇将介绍如何把我们自己的数据通过ArcGIS Server发布出去&#xff0c;并且能够通过Web页面进行显示和编辑。 发布数据服务 在进行WebGIS开发中&#xff0c;地图显示的内容…

MyBatis学习总结(17)——Mybatis分页插件PageHelper

2019独角兽企业重金招聘Python工程师标准>>> 如果你也在用Mybatis&#xff0c;建议尝试该分页插件&#xff0c;这一定是最方便使用的分页插件。 分页插件支持任何复杂的单表、多表分页&#xff0c;部分特殊情况请看重要提示。 想要使用分页插件&#xff1f;请看如何…

微信发力了,一键部署网站后端!

大家好&#xff0c;我是鱼皮。还记得么&#xff1f;之前我全程直播带大家从 0 到 1 做了一个包含前端、后端的 表情包网站项目 &#xff0c;支持搜索表情、自由裁切下载、给表情包配字等功能。爸爸表情包网站在线编辑下载但由于各方面的原因&#xff0c;我暂时将该网站战术下线…

数据可视化(9)--数据可视化6步法

在当前互联网&#xff0c;各种数据可视化图表层出不穷&#xff0c;本文尝试对数据可视化的方法进行归纳&#xff0c;整理成6步法。一般的数据图表都可以拆分成最基本的两类元素: 所描述的事物及这个事物的数值&#xff0c;我们暂且将其分别定义为指标和指标值。比如一个性别分布…

c++win32项目 如何显示后再删除一个绘图_iMATLAB 绘图扩展函数系列 | 让你绘图更自由(进阶专辑开篇)!...

本专辑参考了mathworks公司主页文件交换站的一些分享文件&#xff0c;遴选部分绘图扩展函数供初学者参考&#xff0c;仅用作学习资料传播&#xff0c;版权属于原作者&#xff0c;特此致谢。如有不妥&#xff0c;请联系删除。本专辑将持续更新&#xff0c;欢迎读者投稿自己绘图函…

HTML5:理解head

2019独角兽企业重金招聘Python工程师标准>>> HTML文档的head部分&#xff0c;通常包括指定页面标题&#xff0c;为搜索引擎提供关于页面本身的信息&#xff0c;加载样式表&#xff0c;以及加载JavaScript文件&#xff08;出于性能考虑&#xff0c;多数时候放在页面底…

Dapr项目应用探索

背景介绍前面文章对Dapr的基本信息进行了学习&#xff0c;接下来尝试将Dapr应用相关应用中。接下来一步步实现应用dapr功能。一、预期效果如上图应用Dapr点包含&#xff1a;a) 报表服务绑定统一数据源服务&#xff1a;接受更新通知  b) 业务系统调用报表操作:采用Dapr方式二、…

为什么当代人越来越不快乐?

全世界只有3.14 % 的人关注了爆炸吧知识小时候哭着哭着就笑了&#xff0c;长大后笑着笑着就哭了。生活不易&#xff0c;成年人叹气&#xff0c;房租水费&#xff0c;学习压力、工作不如意...各种无形的压力&#xff0c;压得人喘不过气。如果一绷得太紧&#xff0c;再坚韧的弦也…

解读C#正则表达式

为什么80%的码农都做不了架构师&#xff1f;>>> 多少年来&#xff0c;许多的编程语言和工具都包含对正则表达式的支持&#xff0c;.NET基础类库中包含有一个名字空间和一系列可以充分发挥规则表达式威力的类&#xff0c;而且它们也都与未来的Perl 5中的规则表达式兼…

iphone换机数据迁移_iPhone迁移数据到Android(相册与短信)

2020年09月20日前言&#xff1a;卖掉iPhone7暂时回到Android手机&#xff0c;然后需要将iPhone内的资料迁移到新手机中。我尽量不使用第三方工具实现迁移工作。一般新手机都会有迁移助手&#xff0c;但是都不完美&#xff0c;毕竟是两个不同手机系统&#xff0c;很多东西还是需…

使用 dotnet-outdated 维护项目 nuget 包版本

使用 dotnet-outdated 维护项目 nuget 包版本Intro我们项目中或多或少都会有一些 NuGet 包&#xff0c;使用到 NuGet 包时&#xff0c;如何保证我们的 NuGet 包不会太旧呢&#xff1f;我们可以借助 dotnet-outdated 来检查项目中的 NuGet 包是否有更新Sample首先我们需要执行 d…

被一帮小姐姐围着是什么感觉?

1 阿姨&#xff1a;我靠灵魂呼吸...▼2 医学院护理班男生的日常▼3 嫌自己活太久了&#xff1f;▼4 看来还是作业太少了▼5 小孟老师&#xff0c;您妈&#xff01;▼6 哈哈哈哈哈&#xff0c;不行了...▼7 他今天是不会跟你走的&#xff01;&#xff01;&#xff01;▼8 …

仓库处理中 无法修改_上海电商仓储物流公司,冷链仓库-上海玖日仓储

首页 > 新闻列表 > 浏览文章发布时间&#xff1a;2020-10-21 15:03:33 浏览量&#xff1a; 4导读&#xff1a;上海玖日仓储为您提供上海电商仓储物流公司,冷链仓库的相关知识与详情&#xff1a; 货物出入库扫描功能&#xff0c;同时记录扫描时间&#xff1b;完善订单与仓…

13 个 C# 10 特性

常量的内插字符串C# 10 允许使用在常量字符串初始化中使用插值, 如下const string name "Oleg"; const string greeting $"Hello, {name}.";Console.WriteLine(greeting); // Output: Hello, Oleg.扩展属性模式从 C# 10 开始&#xff0c;您可以在适当的模…

android studio button位置_免费的Android开发环境

Android Studio for mac是一个全面的Android开发环境&#xff0c;Android Studio帮助您设计&#xff0c;构建&#xff0c;测试和调试Android应用程序&#xff0c;利用Android Studio所有特色工具并开发出令人惊叹的应用程序。Android Studio是一个为Android平台开发程序的集成开…

TCP握手/挥手的过程分析

TCP连接建立 在TCP/IP协议中&#xff0c;TCP协议提供可靠的连接服务&#xff0c;采用三次握手建立一个连接。 服务器必须准备好接受外来的连接。这通过调用socket、 bind和listen函数来完成&#xff0c;称为被动打开(passive open)。 第一次握手&#xff1a;客户通过调用connec…