单元测试NUnit,mock组件NSubstitute,信号量SemaphoreSlim,异步lock等例子
public class LockTest
{
private IDatabase _database;
private readonly Random _random = new Random();
private int _num = 0; [SetUp]
public void SetUp()
{
_num = 0; //信号量,同时访问的线程1
var slim = new SemaphoreSlim(1, 1); //mock redis的接口
_database = Substitute.For<IDatabase>(); //mock LockTake 同时只有一个线程可以拿到锁
//slim.WaitAsync 参数为0时标识直接返回是否拿到锁,不会类似lock阻塞直至其他人释放
//这里主要mock redis的场景,拿不到要使用循环重复尝试拿锁,因此传0
//普通异步锁场景根据需求选择等待时间,使用等待时间理论上使用响应时间应比自己写循环简单且有更好的性能
_database.LockTakeAsync(Arg.Any<RedisKey>(), Arg.Any<RedisValue>(), Arg.Any<TimeSpan>())
.Returns(async call => await slim.WaitAsync(call.ArgAt<TimeSpan>(2))); //mock LockRelease 释放锁
_database.LockReleaseAsync(Arg.Any<RedisKey>(), Arg.Any<RedisValue>()).Returns(call =>
{
slim.Release();
return true;
});
} /// <summary>
/// 使用锁的版本,_num值会按预期加至5
/// </summary>
/// <returns></returns>
[Test]
public async Task WithLockTest()
{
var tasks = Enumerable.Range(1, 5).Select(c => LockTestTaskInner("1", "1", TimeSpan.FromSeconds(0)));
await Task.WhenAll(tasks);
Assert.AreEqual(_num, 5);
} /// <summary>
/// 无锁版本,_num值会配其他线程覆盖
/// </summary>
/// <returns></returns>
[Test]
public async Task WithoutLockTestTask()
{
var tasks = Enumerable.Range(1, 5).Select(async c =>
{
var tmp = _num;
//模拟覆盖写
await Task.Delay(_random.Next(5));
_num = tmp + 1;
});
await Task.WhenAll(tasks);
Console.WriteLine(_num);
Assert.AreNotEqual(_num, 5);
} private async Task LockTestTaskInner(string key, string value, TimeSpan expiry)
{
var reTryGetLock = true;
while (reTryGetLock)
{
var taskLockSuccess = await _database.LockTakeAsync(key, value, expiry);
if (taskLockSuccess)
{
reTryGetLock = false;
try
{
var tmp = _num;
//模拟覆盖写
await Task.Delay(_random.Next(5));
_num = tmp + 1;
}
finally
{
await _database.LockReleaseAsync(key, value);
}
}
else
{
//证明LockTakeAsync不会阻塞
//Console.WriteLine("retry");
await Task.Delay(_random.Next(10));
}
} }
单元测试NUnit,mock组件NSubstitute,信号量SemaphoreSlim,异步lock等例子的更多相关文章
- Spring Boot单元测试(Mock)
Spring Boot单元测试(Mock) Java个人学习心得 2017-08-12 16:07 Mock 单元测试的重要性就不多说了,我这边的工程一般都是Spring Boot+Mybatis(详 ...
- MVC文件上传04-使用客户端jQuery-File-Upload插件和服务端Backload组件实现多文件异步上传
本篇使用客户端jQuery-File-Upload插件和服务端Badkload组件实现多文件异步上传.MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小 ...
- Java单元测试(Junit+Mock+代码覆盖率)---------转
Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测 ...
- c# 异步调用简单例子(转载)
首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...
- 并发教程--JAVA5中 计数信号量(Counting Semaphore)例子
并发教程--JAVA5中 计数信号量(COUNTING SEMAPHORE)例子 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java中的计数信息量(C ...
- NUnit+mock+moq单元测试
[TestFixture] public class InstantBatchBuyTest { private string _mallAbc; private string _itemCode; ...
- 企业应用架构研究系列二十六:信号量SemaphoreSlim与Semaphore
在进行多线程程序的开发和设计的过程中,不可避免的需要引入semaphore信号量这个组件,这是.net框架提供的一个对多线程计数互斥的方案,就是允许指定的线程个数访问特定的资源而增加的 一个" ...
- Python3的单元测试模块Mock与性能测试模块CProfile
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_92 我们知道写完了代码需要自己跑一跑进行测试,一个写好的程序如果连测试都没有就上到生产环境是不敢想象的,这么做的人不是太自信就是太 ...
- Python单元测试和Mock测试
单元测试 测试可以保证你的代码在一系列给定条件下正常工作 测试允许人们确保对代码的改动不会破坏现有的功能 测试迫使人们在不寻常条件的情况下思考代码,这可能会揭示出逻辑错误 良好的测试要求模块化,解耦代 ...
随机推荐
- 深度学习——手动实现残差网络ResNet 辛普森一家人物识别
深度学习--手动实现残差网络 辛普森一家人物识别 目标 通过深度学习,训练模型识别辛普森一家人动画中的14个角色 最终实现92%-94%的识别准确率. 数据 ResNet介绍 论文地址 https:/ ...
- Using C++ in VS Code
Using C++ in VS Code Get Started with C++ and Windows Subsystem for Linux in Visual Studio Code ...
- Golang通脉之数据类型
标识符与关键字 在了解数据类型之前,先了解一下go的标识符和关键字 标识符 在编程语言中标识符就是定义的具有某种意义的词,比如变量名.常量名.函数名等等. Go语言中标识符允许由字母数字和_(下划线) ...
- CentOS 压缩解压
目录 命令 tar gzip.gunzip bzip2.bunzip2 zip.unzip 命令组合 打包:将多个文件合成一个总的文件,这个总的文件通常称为"归档". 压缩:将一个 ...
- 如何使用远程工具连接Linux服务器
大家好,今天我想和大家分享一下Linux如何连接远程控制工具我们都知道,Linux是著名的开源服务器操作系统,而在运维工程师的实际工作当中,我们不大可能时时刻刻都在服务器本地操作.因此这时,我们要用远 ...
- [no_code][Beta]设计和计划
2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 Beta设计和计划 我们在这个课程的目标是 远程协同工作,采用最新技术开发软件 这个作业在哪个具体 ...
- 设置nginx进程可打开最大的文件数
涉及到的nginx配置参数: worker_processes: 表示操作系统启动多少个工作进程在运行,一般这个参数设置成CPU核数的倍数 worker_connections:表示nginx的工作进 ...
- BOOST内存管理-intrusive_ptr
参考链接https://blog.csdn.net/harbinzju/article/details/6754646 intrusive_ptr 是shared_ptr的插入式版本.与shared_ ...
- matplotlib.legend()函数用法
用的较多,作为记录 legend语法参数如下: matplotlib.pyplot.legend(*args, **kwargs) 几个暂时主要用的参数: (1)设置图例位置 使用loc参数 plt. ...
- cURL 命令获取本机外网 IP
1.1 查询本机外网 IP # curl dhcp.cn 134.175.159.160 1.2 输出格式为 JSON # curl dhcp.cn/?json { "IP": & ...