.NET单元测试(五):多线程
鉴于.NET Framework 4.5后.NET增加了对 async/await 的支持,本文讨论的异步内容均基于async/await
客户端界面开发,多线程是逃不了的话题,而多线程的加入势必对程序的稳定性带来挑战,单元测试就显得更为重要。相对于同步代码的测试,多线程单元测试有更多细节需要注意。
async void 和 async Task。
假设某一天你运气不好,需要为类似如下的方法补充单元测试:
public static bool Changed;public static async void ChangeAsync()
{await Task.Run(() =>{Task.Delay(1000);Changed = true;});
}
复制代码
你发现,要测试此方法需要用一些奇葩的方式,比如:
[TestMethod()]
public void ChangeAsyncTest_OriginalFalse_ChangeToTrue()
{AsyncClient.Changed = false;AsyncClient.ChangeAsync();Thread.Sleep(1100);Assert.IsTrue(AsyncClient.Changed);
}
复制代码
显然,这种延时等待是极其恶心的,如果ChangeAsync方法返回的不是void而是Task,我们就可以愉快的await了:
[TestMethod()]
public async Task ChangeAsyncTest_OriginalFalse_ChangeToTrue()
{AsyncClient.Changed = false;await AsyncClient.ChangeAsync();Assert.IsTrue(AsyncClient.Changed);
}
复制代码
需要特别注意的是,在异步单元测试方法中也必须返回Task,这是MSTest的约定,否则这个测试方法无法运行起来。(实际上MSTest也需要使用返回的Task来收集异常,关于这部分更多内容可以参见Async/Await最佳实践)
抛弃ExpectedException
在测试程序是否按照预期的抛出了异常,我们常常会用ExpectedException,这家伙有一个问题,它是对整个测试方法的方法体做捕获,也就是说测试方法中的非action代码抛出了异常依然能够被ExpectedException捕获,这就造成潜在的bug,为了解决此问题,在MSTest V2之前往往需要写一些辅助方法,但MSTest V2断言库中增加了Assert.ThrowsExceptionAsync和Assert.ThrowsException,可以精确的定位在哪段代码中抛出了异常。假设我们的被测代码跟下面类似:
public static async Task ChangeAsync()
{await Task.Run(() =>{throw new InvalidOperationException();});
}
复制代码
测试代码可以这样写:
[TestMethod()]
public async Task ChangeAsyncTest_ThrowInvalidOperationException()
{await Assert.ThrowsExceptionAsync<InvalidOperationException>(async () =>{await AsyncClient.ChangeAsync();});
}
复制代码
异步方法mock
在moq中,异步方法的mock也是极其简单的,假设有这样的接口:
public interface ITextReader
{Task<string> ReadTextAsync();
}
复制代码
测试代码中mock其返回结果可以有如下两种写法:
var mockTextReader = new Mock<ITextReader>();//可以这样
mockTextReader.Setup(x => x.ReadTextAsync()).Returns(async ()=>await Task.FromResult("mockValue"));//也可以这样
mockTextReader.Setup(x => x.ReadTextAsync()).ReturnsAsync(()=> "mockValue");
复制代码
2017-11-30 15:26:34
转载于:https://juejin.im/post/5ce55aa3e51d4576bc1a0d58
.NET单元测试(五):多线程相关推荐
- C#多线程学习(五) 多线程的自动管理(定时器) (转载系列)——继续搜索引擎研究...
Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer ...
- Java之多线程学习笔记五 —— 多线程模拟龟兔赛跑
Java之多线程学习笔记五 -- 多线程模拟龟兔赛跑 参考教程B站狂神https://www.bilibili.com/video/BV1V4411p7EF package pers.ylw.less ...
- JUnit单元测试中多线程的坑
一.JUnit单元测试方法不输出 在JUnit的@Test方法中启用多线程,新启动的线程会随着@Test主线程的死亡而不输出 二.解决方法 在@Test方法中每创建一个线程,就join一下,这样我们新 ...
- 【机器视觉】 HDevelop语言基础(五)-多线程
00. 目录 文章目录 00. 目录 01. 概述 02. 启动线程 03. 等待子线程结束 04. HDevelop中线程的执行 05. 监视线程 06. 挂起和恢复线程 06. 附录 01. 概述 ...
- [19/04/12-星期五] 多线程_任务定时调度(Timer、Timetask和QUARTZ)
一.Timer和Timetask 通过Timer和Timetask,我们可以实现定时启动某个线程. java.util.Timer 在这种实现方式中,Timer类作用是类似闹钟的功能,也就是定时或者每 ...
- C#多线程学习(五) 多线程的自动管理(定时器)
Timer类:设置一个定时器,定时执行用户指定的函数. 定时器启动后,系统将自动建立一个新的线程,执行用户指定的函数. 初始化一个Timer对象: Timer timer ...
- 在Eclipse中使用JUnit4进行单元测试
在Eclipse中使用JUnit4进行单元测试 http://www.sina.com.cn 2010年01月18日 14:08 IT168.com [IT168 技术文档]我们在编写大型程序的时 ...
- C#多线程学习(四) 多线程的自动管理(线程池) (转载系列)——继续搜索引擎研究...
在多线程的程序中,经常会出现两种情况: 一种情况: 应用程序中,线程把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应 这一般使用ThreadPo ...
- 艾伟:C#多线程学习(六) 互斥对象
本系列文章导航 C#多线程学习(一) 多线程的相关概念 C#多线程学习(二) 如何操纵一个线程 C#多线程学习(三) 生产者和消费者 C#多线程学习(四) 多线程的自动管理(线程池) C#多线程学习( ...
- C# 多线程学习总结
C#多线程学习(一) 多线程的相关概念 什么是进程? 当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的. 什么是线程? 线程是 ...
最新文章
- android网络游戏开发实战pdf_Python项目开发实战+第2版PDF高清文档下载
- hihoCoder #1384 : Genius ACM [枚举+倍增]
- AI理论知识基础(21)-对变化建模-用差分方程-动力系统及常数解
- 深交所与工信部签署优质中小企业上市培育战略合作协议
- LINUX下的GNU调试工具,GNU调试器 GDB 8.3 发布及安装更新,支持RISC-V与IPv6连接等
- 语法的集合?协议可没那么简单
- matlab索引超出数组边界且不提示数组边界的一种处理办法
- 弘辽科技:直通车引流逻辑。
- 随机数相关函数rand与srand 以及drand48()与srand48
- 0门槛项目,闲鱼卖特价电影票,免费低价票源
- mysql table already_MySQL优化表时提示 Table is already up to date的解决方法
- 【杂烩】Tesla M40 24G 在Win11上的双显卡显示实现、改风冷
- BAT 字符串大小写转换
- 基于Java毕业设计影院网上售票系统源码+系统+mysql+lw文档+部署软件
- 数据可视化 信息可视化_数据可视化极性
- 一体化运维:挖矿病毒可能正在蚕食你的IT资源
- 从零构建FLINK整合Drools动态规则实时运营系统(项目案例)第1篇(项目介绍篇)
- 计算机远程桌面在什么地方查找,远程桌面连接怎么使用,远程桌面连接在哪里...
- 315/433M 无线发射芯片 XL4456 功能和用途简单介绍
- 国外的站长如何做SEO优化?
热门文章
- 别怨自己命不好,先看看“厚德载物”你有几德?
- libcurl 发送邮件_libcurl smtp发送邮件附件大小限制问题
- 长春技师学院计算机系,长春技校排名前五十
- html target=_blank 弹出独立窗口,HTML base 标签的 target 属性 —— base target=_blank /...
- js 键盘事件 理解
- liunx服务器间拷贝文件,linux 不同服务器之间拷贝文件
- echarts 按需引入模_【React】react项目引入echarts插件
- 时间java_Java 日期时间
- python 3.8.5 打包_骚操作 | Python 实现在 App 端的人脸识别
- 中南大学MATLAB变量专题/矩阵的建立1-3/4