using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using StackExchange.Redis; using Xunit; using Xunit.Extensions; using Xunit.Serialization; using Xunit.Abstractions; using Xunit.Sdk; using RedisStudyModel; using RedisStuy; namespace RedisStudyTest { /// /// Redis Hash 类型测试 /// [Trait("RedisHash", "All")] public class RedisHashStudyTest : IDisposable { #region 初始化 private readonly ITestOutputHelper testOutput; private IDatabase redisDatabase = null; private RedisHashStudy redisHashStudy = null; private List defaultStudentList; private Student defaultStudent = null; private string preStudentHashKey = "RedisStudy:Student:"; private string defaultStudentHashKey = ""; private int defaultExpireSeconds = 20; /// /// 构造 /// public RedisHashStudyTest(ITestOutputHelper output) { this.testOutput = output; redisDatabase = RedisHelper.GetRedisDatabase(); redisHashStudy = new RedisHashStudy(); defaultStudent = new Student() { Id = 1, Name = "王高峰", Age = 18 }; defaultStudentHashKey = preStudentHashKey + defaultStudent.Id; defaultStudentList = new List() { new Student() { Id = 1001, Name = "王高峰", Age = 11 }, new Student() { Id = 1002, Name = "王高峰2", Age = 22 }, new Student() { Id = 1003, Name = "王高峰3", Age = 33 }, new Student() { Id = 1004, Name = "王高峰4", Age = 44 }, new Student() { Id = 1005, Name = "王高峰5", Age = 55 }, }; //删理默认学生 DeleteExitsStudents(); } #endregion #region HashSet /// /// xUnit输出信息 测试 /// [Trait("RedisHash", "HashSet")] [Fact(DisplayName = "HashSet 输出信息测试")] public void HashSetOutputTest() { Assert.True(true); testOutput.WriteLine("我是xUnit测试输出信息"); } /// /// 参数异常 测试 /// [Trait("RedisHash", "HashSet")] [Fact(DisplayName = "HashSet 异常测试")] public void HashSetExceptionTest() { string redisKey = preStudentHashKey + defaultStudent.Id; //参数异常测试 Assert.Throws(() => redisHashStudy.HashSet(string.Empty, null)); Assert.Throws(() => redisHashStudy.HashSet("", null)); Assert.Throws(() => redisHashStudy.HashSet(preStudentHashKey + "-1", null)); Assert.Throws(() => redisHashStudy.HashSet(preStudentHashKey + "-1", new HashEntry[] { })); } /// /// 参数 When 测试 /// [Trait("RedisHash", "HashSet")] [Fact(DisplayName = "HashSet When参数测试")] public void HashSetWhenTest() { string redisKey = preStudentHashKey + defaultStudent.Id; //当前上下文不能使用: When.Exists var id_When_NotExists_No = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists); Assert.True(id_When_NotExists_No); var id_When_NotExists_Yes = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists); Assert.False(id_When_NotExists_Yes); var id_When_Always_Exists = redisHashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.Always); Assert.False(id_When_Always_Exists); var id_When_Always_NotExists = redisHashStudy.HashSet(redisKey, "Id4", defaultStudent.Id + 1, When.Always); Assert.True(id_When_Always_NotExists); } /// /// 添加一个默认学生 测试 /// [Trait("RedisHash", "HashSet")] [Fact] public void HashSetAddStudentTest() { var studentEntries = new HashEntry[] { new HashEntry("Id",defaultStudent.Id), new HashEntry("Name",defaultStudent.Name), new HashEntry("Age",defaultStudent.Age), }; //插入Sudent var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries, CommandFlags.None); Assert.True(addHash); //设置过期 redisDatabase.KeyExpire(defaultStudentHashKey, TimeSpan.FromSeconds(defaultExpireSeconds)); } /// /// 添加一组初始化设置的学生 测试 /// [Trait("RedisHash", "HashSet")] [Fact] public void HashSetAddGroupStudentTest() { foreach (var temp in defaultStudentList) { string redisKey = preStudentHashKey + temp.Id; var studentEntries = new HashEntry[] { new HashEntry("Id", temp.Id), new HashEntry("Name", temp.Name), new HashEntry("Age", temp.Age), }; //插入Sudent var addStudent = redisHashStudy.HashSet(redisKey, studentEntries); Assert.True(addStudent); //设置过期 redisDatabase.KeyExpire(redisKey, TimeSpan.FromSeconds(defaultExpireSeconds)); } //清理删除 foreach (var temp in defaultStudentList) { redisDatabase.KeyDelete(preStudentHashKey + temp.Id); } } /// /// 设置一个哈希字段 测试 /// [Trait("RedisHash", "HashSet")] [Fact] public void HashSetHashfieldTest() { Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id)); Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id)); Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", defaultStudent.Name)); Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Name", defaultStudent.Name)); Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Age", defaultStudent.Age)); Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Age", defaultStudent.Age)); } /// /// 设置一组哈希字段 测试 /// [Fact] public void HashSetGroupHashfieldTest() { Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id)); Assert.False(redisHashStudy.HashSet(defaultStudentHashKey, "Id", defaultStudent.Id + 1)); var entrys = new HashEntry[] { new HashEntry("Name", defaultStudent.Name), new HashEntry("Age", defaultStudent.Age), }; var entrys2 = new HashEntry[] { new HashEntry("Name", defaultStudent.Name+"2"), new HashEntry("Age", defaultStudent.Age+1), }; Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, entrys)); Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, entrys2)); } /// /// 特例测试:给key为string.Empty的哈希 设置字段 /// 结 果:添加或更新操作正常。只是"Redis Desktop Manager"管理工具显示空白 /// [Trait("RedisHash", "HashSet")] [Fact] public void HashSetForEmptyKeyTest() { //清理遗留数据 redisDatabase.KeyDelete(string.Empty); var result = redisHashStudy.HashSet(string.Empty, "Name", "wanggaofeng"); Assert.True(result); var fieldValue = redisDatabase.HashGet(string.Empty, "Name"); Assert.Equal("wanggaofeng", fieldValue); result = redisHashStudy.HashSet(string.Empty, "Name", "wangxiangqian"); Assert.False(result); fieldValue = redisDatabase.HashGet(string.Empty, "Name"); Assert.Equal("wangxiangqian", fieldValue); //清理 redisDatabase.KeyDelete(string.Empty); } /// /// 特例测试:给字段名为空串的哈希 设置字段 /// 结 果:添加或更新操作正常。只是"Redis Desktop Manager"管理工具显示空白 /// [Trait("RedisHash", "HashSet")] [Fact] public void HashSetForEmptyFieldTest() { //添加正常 var result = redisHashStudy.HashSet(defaultStudentHashKey, "", defaultStudent.Id); Assert.True(result); var fieldValue = redisHashStudy.HashGet(defaultStudentHashKey, ""); Assert.Equal(defaultStudent.Id, fieldValue); //更新正常 result = redisHashStudy.HashSet(defaultStudentHashKey, "", defaultStudent.Id + 1); Assert.False(result); fieldValue = redisHashStudy.HashGet(defaultStudentHashKey, ""); Assert.Equal(defaultStudent.Id+1, fieldValue); } #endregion #region HashDecrement /// /// 字段值不是数字时,异常 /// 原注释:字段不为数据字,则改为数字 /// 实际执行:抛出异常,不知道是原注释错误,还是其它原因 /// [Fact] public void HashDecrementExceptionTest() { Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng")); Assert.Throws(() => redisHashStudy.HashDecrement(defaultStudentHashKey, "Name", 1)); } /// /// 哈希表不存在 /// 则先创建哈希表,再添加值为0的字段,然后执行自减操作 /// [Fact] public void HashDecrementHashKeyTest() { //Key不存在,先创建哈希表,再添加值为0的字段,然后执行自减操作 Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Id", 1)); //存在,直接自减 Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Id")); } /// /// 自减字段不存在 /// 先添加字段,值设为0,然后执行自减操作 /// [Fact] public void HashDecrementHashFieldTest() { //字段不存在,则创建之 Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1)); Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Age")); } /// /// 自减负数,则自增 /// [Fact] public void HashDecrementMinusTest() { //自减负数时,则自增 Assert.Equal(2, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", -2)); } /// /// 自减整数 /// [Fact] public void HashDecrementByIntTest() { //字段减少1 Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1)); //字段减少2 Assert.Equal(-3, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2)); } /// /// 自减浮点数 /// 断言应该用精度值在一个小范围内 /// [Fact] public void HashDecrementByDoubleTest() { //新字段时,可以用相等比较 var dec = redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2.1); var absDec = Math.Abs(-2.1 - dec); Assert.Equal(0, absDec); //已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围 dec = redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2.5); absDec = Math.Abs(-4.6 - dec); Assert.True(absDec < 0.01); } #endregion HashIncrement #region HashIncrement /// /// 字段值不是数字时,异常 /// 原注释:字段不为数据字,则改为数字 /// 实际执行:抛出异常,不知道是原注释错误,还是其它原因 /// [Fact] public void HashIncrementExceptionTest() { Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng")); Assert.Throws(() => redisHashStudy.HashIncrement(defaultStudentHashKey, "Name", 1)); } /// /// 哈希表不存在 /// 则先创建哈希表,再添加值为0的字段,然后执行自增操作 /// [Fact] public void HashIncrementHashKeyTest() { //Key不存在,先创建哈希表,再添加值为0的字段,然后执行自减操作 Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1)); Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Id")); } /// /// 自增字段不存在 /// 先添加字段,值设为0,然后执行自增操作 /// [Fact] public void HashIncrementHashFieldTest() { //字段不存在,则创建之 Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1)); Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Age")); } /// /// 自增负数,则自减 /// [Fact] public void HashIncrementMinusTest() { //自增负数时,则自减 Assert.Equal(-2, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", -2)); } /// /// 自增整数 /// [Fact] public void HashIncrementByIntTest() { //字段减少1 Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1)); //字段减少2 Assert.Equal(3, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2)); } /// /// 自增浮点数 /// 断言应该用精度值在一个小范围内 /// [Fact] public void HashIncrementByDoubleTest() { //新字段时,可以用相等比较 var dec = redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2.1); var absDec = Math.Abs(2.1 - dec); Assert.Equal(0, absDec); //已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围 dec = redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2.5); absDec = Math.Abs(4.6 - dec); Assert.True(absDec < 0.01); } #endregion #region HashGetAll /// /// 获取一个学生 /// [Fact] public void HashGetAllTest() { var studentEntries = new HashEntry[] { new HashEntry("Id",defaultStudent.Id), new HashEntry("Name",defaultStudent.Name), new HashEntry("Age",defaultStudent.Age), }; //插入Sudent var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries); Assert.True(addHash); var entries = redisHashStudy.HashGetAll(defaultStudentHashKey); Assert.NotNull(entries); Student myStudent = new Student() { Id = (int)entries.FirstOrDefault(e => e.Name == "Id").Value, Name = entries.FirstOrDefault(e => e.Name == "Name").Value, Age = (int)entries.FirstOrDefault(e => e.Name == "Age").Value, }; Assert.True(myStudent.Id == defaultStudent.Id && myStudent.Name == defaultStudent.Name && myStudent.Age == defaultStudent.Age); } #endregion #region HashGet /// /// 哈希表不存在时,获取字段值 /// [Fact] public void HashGetNotKkeyTest() { var result = redisHashStudy.HashGet(defaultStudentHashKey, "Id"); Assert.False(result.HasValue); } /// /// 字段不存在时,获取字段值 /// [Fact] public void HashGetNotHashfieldTest() { redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1); var result = redisHashStudy.HashGet(defaultStudentHashKey, "Name"); Assert.False(result.HasValue); } [Fact] public void HashGetOneFieldTest() { AddDefaultStudent(); Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Id")); Assert.Equal(defaultStudent.Name, redisHashStudy.HashGet(defaultStudentHashKey, "Name", CommandFlags.None)); Assert.Equal(defaultStudent.Age, redisHashStudy.HashGet(defaultStudentHashKey, "Age", CommandFlags.None)); } [Fact] public void HashGetGroupFieldTest() { AddDefaultStudent(); RedisValue[] hashFields = new RedisValue[] { "Id", "Name", "Age", }; RedisValue[] resultValues = redisHashStudy.HashGet(defaultStudentHashKey, hashFields, CommandFlags.None); Assert.Contains(defaultStudent.Id, resultValues); Assert.Contains(defaultStudent.Name, resultValues); Assert.Contains(defaultStudent.Age, resultValues); } #endregion #region HashKeys /// /// 哈希不存在时,获取所有字段的Key /// [Fact] public void HashKeysNotKeyTest() { RedisValue[] keys = redisHashStudy.HashKeys(defaultStudentHashKey); Assert.NotNull(keys); Assert.Empty(keys); } /// /// 获取哈希所有字段的Key /// [Fact] public void HashKeys() { AddDefaultStudent(); RedisValue[] keys = redisHashStudy.HashKeys(defaultStudentHashKey); Assert.NotEmpty(keys); Assert.Contains("Id", keys); Assert.Contains("Name", keys); Assert.Contains("Age", keys); } #endregion #region HashValues /// /// 哈希不存在时,获取所有字段的Key /// [Fact] public void HashValuesNotKeyTest() { RedisValue[] keys = redisHashStudy.HashValues(defaultStudentHashKey); Assert.NotNull(keys); Assert.Empty(keys); } /// /// 获取哈希所有字段的Key /// [Fact] public void HashValues() { AddDefaultStudent(); RedisValue[] values = redisHashStudy.HashValues(defaultStudentHashKey); Assert.NotEmpty(values); Assert.Contains(defaultStudent.Id, values); Assert.Contains(defaultStudent.Name, values); Assert.Contains(defaultStudent.Age, values); } #endregion #region HashLength /// /// 哈希不存在时,获取字段数 /// [Fact] public void HashLengthNotKeyTest() { var result = redisHashStudy.HashLength(defaultStudentHashKey); Assert.Equal(0, result); } /// /// 获取哈希字段数 /// [Fact] public void HashLengthTest() { AddDefaultStudent(); var result = redisHashStudy.HashLength(defaultStudentHashKey); Assert.Equal(3, result); } #endregion #region HashScan /// /// 哈希不存在时,HashScan /// [Fact] public void HashScanNotKeyTest() { var hashEntrys = redisHashStudy.HashScan(defaultStudentHashKey, "*", 20, CommandFlags.None); var num = hashEntrys.Count(); Assert.Equal(0, num); var entryList = hashEntrys.ToList(); Assert.Empty(entryList); } /// /// 简单测试,有单独测试类详细测试 /// [Fact] public void HashScanTest() { //插入多列hash List hashEntries = new List(); for (int i = 1; i <= 100; i++) { hashEntries.Add(new HashEntry("Field" + i, i)); } redisHashStudy.HashSet(defaultStudentHashKey, hashEntries.ToArray()); var hashFieldScan = redisHashStudy.HashScan(defaultStudentHashKey); Assert.Equal(100, hashFieldScan.Count()); var scanTake = hashFieldScan.Skip(10).Take(10).ToList(); Assert.Equal(10, scanTake.Count()); //删除hash redisDatabase.KeyDelete(defaultStudentHashKey); } [Fact] public void HashScan2Test() { //插入多列hash List hashEntries = new List(); for (int i = 1; i <= 100; i++) { hashEntries.Add(new HashEntry("Field" + i, i)); } redisHashStudy.HashSet(defaultStudentHashKey, hashEntries.ToArray()); var hashFieldScan = redisHashStudy.HashScan(defaultStudentHashKey, "*", 20, 0, 0, CommandFlags.None); Assert.Equal(100, hashFieldScan.Count()); } #endregion #region HashExists /// /// 指定字段是否存在 /// [Fact] public void HashExists() { var studentEntries = new HashEntry[] { new HashEntry("Id",defaultStudent.Id), new HashEntry("Name",defaultStudent.Name), }; //插入Sudent var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries); Assert.True(addHash); Assert.True(redisHashStudy.HashExists(defaultStudentHashKey, "Id")); Assert.True(redisHashStudy.HashExists(defaultStudentHashKey, "Name")); Assert.False(redisHashStudy.HashExists(defaultStudentHashKey, "Age")); } #endregion #region HashDelete /// /// 哈希不存在时,删除哈希字段 /// [Fact] public void HashDeleteNotKeyTest() { var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "FieldFirst"); Assert.False(hashDeleteResult); } /// /// 删除不存在的哈希字段 /// [Fact] public void HashDeleteNotFieldTest() { redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1); var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Name"); Assert.False(hashDeleteResult); } /// /// 删除哈希一个字段 /// [Fact] public void HashDeleteTest() { AddDefaultStudent(); var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Id"); Assert.True(hashDeleteResult); hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Name", CommandFlags.None); Assert.True(hashDeleteResult); hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Age", CommandFlags.None); Assert.True(hashDeleteResult); } /// /// 删除一组哈希字段 /// [Fact] public void HashDeleteGroupFieldTest() { AddDefaultStudent(); RedisValue[] delValues = new RedisValue[] { "Id", "Name", "Age", }; var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, delValues, CommandFlags.None); Assert.Equal(3, hashDeleteResult); } #endregion #region HashKeyDelete /// /// 删除学生 /// [Fact] public void KeyDeleteTest() { Assert.False(redisDatabase.KeyDelete(preStudentHashKey + "-2000")); } #endregion /// /// 清理 /// public void Dispose() { DeleteExitsStudents(); } #region 辅助方法 /// /// 删除Redis中的测试学生 /// private void DeleteExitsStudents() { if (defaultStudent != null) { redisDatabase.KeyDelete(preStudentHashKey + defaultStudent.Id); } } private void AddDefaultStudent() { var studentEntries = new HashEntry[] { new HashEntry("Id",defaultStudent.Id), new HashEntry("Name",defaultStudent.Name), new HashEntry("Age",defaultStudent.Age), }; //插入Sudent var addHash = redisHashStudy.HashSet(defaultStudentHashKey, studentEntries); } #endregion } }