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等例子的更多相关文章

  1. Spring Boot单元测试(Mock)

    Spring Boot单元测试(Mock) Java个人学习心得 2017-08-12 16:07 Mock 单元测试的重要性就不多说了,我这边的工程一般都是Spring Boot+Mybatis(详 ...

  2. MVC文件上传04-使用客户端jQuery-File-Upload插件和服务端Backload组件实现多文件异步上传

    本篇使用客户端jQuery-File-Upload插件和服务端Badkload组件实现多文件异步上传.MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小  ...

  3. Java单元测试(Junit+Mock+代码覆盖率)---------转

    Java单元测试(Junit+Mock+代码覆盖率) 原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测 ...

  4. c# 异步调用简单例子(转载)

    首先来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日 ...

  5. 并发教程--JAVA5中 计数信号量(Counting Semaphore)例子

    并发教程--JAVA5中 计数信号量(COUNTING SEMAPHORE)例子 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java中的计数信息量(C ...

  6. NUnit+mock+moq单元测试

    [TestFixture] public class InstantBatchBuyTest { private string _mallAbc; private string _itemCode; ...

  7. 企业应用架构研究系列二十六:信号量SemaphoreSlim与Semaphore

    在进行多线程程序的开发和设计的过程中,不可避免的需要引入semaphore信号量这个组件,这是.net框架提供的一个对多线程计数互斥的方案,就是允许指定的线程个数访问特定的资源而增加的 一个" ...

  8. Python3的单元测试模块Mock与性能测试模块CProfile

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_92 我们知道写完了代码需要自己跑一跑进行测试,一个写好的程序如果连测试都没有就上到生产环境是不敢想象的,这么做的人不是太自信就是太 ...

  9. Python单元测试和Mock测试

    单元测试 测试可以保证你的代码在一系列给定条件下正常工作 测试允许人们确保对代码的改动不会破坏现有的功能 测试迫使人们在不寻常条件的情况下思考代码,这可能会揭示出逻辑错误 良好的测试要求模块化,解耦代 ...

随机推荐

  1. 前端快闪四: 拦截axios请求和响应

    马甲哥继续在同程艺龙写一点大前端: 今天我们来了解一下 如何拦截axios请求/响应? axios是一个基于 promise 的网络请求库,可以用于浏览器和 node.js, promise 类似于C ...

  2. tomcat启动程序报错

    1.问题 23-Apr-2021 10:53:38.897 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.de ...

  3. redis编译安装、哨兵、集群

    编译安装 #下载源代码解压 wget https://download.redis.io/releases/redis-5.0.13.tar.gz -P /home/ tar -xvf /home/r ...

  4. python中的信号通信 blinker

    信号: 信号是一种通知或者说通信的方式,信号分为发送方和接收方.发送方发送一中信号,接收方收到信号的进程会跳入信号处理函数,执行完后再跳回原来的位置继续执行.常见的linux中的信号,通过键盘输入Ct ...

  5. 最详细的Android SDK下载安装及配置教程-------全文均为引用

    <https://www.cnblogs.com/gufengchen/p/11038029.html>

  6. 【UE4】GAMES101 图形学作业0:矩阵初识

    作业描述 给定一个点P=(2,1), 将该点绕原点先逆时针旋转45◦,再平移(1,2), 计算出变换后点的坐标(要求用齐次坐标进行计算). UE4 知识点 主要矩阵 FMatrix FBasisVec ...

  7. BUAA_2020_软件工程_热身作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 热身作业要求 我在这个课程的目标 了解软件工程的技术,掌握工程化开发的能力 这个作业在哪个具体方面 ...

  8. Go语言核心36讲(Go语言进阶技术八)--学习笔记

    14 | 接口类型的合理运用 前导内容:正确使用接口的基础知识 在 Go 语言的语境中,当我们在谈论"接口"的时候,一定指的是接口类型.因为接口类型与其他数据类型不同,它是没法被实 ...

  9. 2021.10.26考试总结[冲刺NOIP模拟16]

    T1 树上的数 \(DFS\)一遍.结构体存边好像更快? \(code:\) T1 #include<bits/stdc++.h> using namespace std; namespa ...

  10. 期望dp好题选做

    前言: 最近连考两场期望dp的题目,sir说十分板子的题目我竟然一点也不会,而且讲过以后也觉得很不可改.于是开个坑. 1.晚测10 T2 大佬(kat) 明明有\(O(mlog)\)的写法,但是\(m ...