From aa22dfc6e37f1d9500efaf3fcf9a073a1c5853f2 Mon Sep 17 00:00:00 2001 From: ruyu Date: Sun, 24 Jun 2018 02:01:04 +0800 Subject: [PATCH] Redis Hash Test --- RedisStudyTest/RedisHashStudyTest.cs | 539 ++++++++++++++++++++++----- RedisStuy/RedisHashStudy.cs | 2 +- 2 files changed, 442 insertions(+), 99 deletions(-) diff --git a/RedisStudyTest/RedisHashStudyTest.cs b/RedisStudyTest/RedisHashStudyTest.cs index d5adf8b..dd5b1a8 100644 --- a/RedisStudyTest/RedisHashStudyTest.cs +++ b/RedisStudyTest/RedisHashStudyTest.cs @@ -21,26 +21,34 @@ namespace RedisStudyTest public class RedisHashStudyTest : IDisposable { #region 初始化 + private readonly ITestOutputHelper testOutput; + private IDatabase redisDatabase = null; private RedisHashStudy hashStudy = null; private List students; - private Student student = null; + private Student defaultStudent = null; private string preHashKey = "RedisStudy:Student:"; + private string defaultHashKey = ""; private int keyExpireSeconds = 20; /// /// 构造 /// - public RedisHashStudyTest() + public RedisHashStudyTest(ITestOutputHelper output) { + this.testOutput = output; + redisDatabase = RedisHelper.GetRedisDatabase(); hashStudy = new RedisHashStudy(); - student = new Student() + defaultStudent = new Student() { Id = 1, Name = "王高峰", - Age = 2 * 9 + Age = 18 }; + + defaultHashKey = preHashKey + defaultStudent.Id; + students = new List() { new Student() @@ -74,20 +82,28 @@ namespace RedisStudyTest Age = 55 }, }; - DeleteExitsStudents(); } #endregion - #region 添加或更新学生 + #region HashSet + /// + /// xUnit输出信息 测试 + /// + [Fact(DisplayName = "HashSet 输出信息测试")] + public void HashSetOutputTest() + { + Assert.True(true); + testOutput.WriteLine("我是xUnit测试输出信息"); + } /// /// 参数异常 测试 /// - [Fact] - public void AddStudentExceptionTest() + [Fact(DisplayName = "HashSet 异常测试")] + public void HashSetExceptionTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; //参数异常测试 Assert.Throws(() => hashStudy.HashSet(string.Empty, null)); Assert.Throws(() => hashStudy.HashSet("", null)); @@ -98,23 +114,24 @@ namespace RedisStudyTest /// /// 参数 When 测试 /// - [Fact] - public void AddStudentWhenTest() + [Trait("HashSet", "When")] + [Fact(DisplayName = "HashSet When参数测试")] + public void HashSetWhenTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; //当前上下文不能使用: When.Exists - var id_When_NotExists_No = hashStudy.HashSet(redisKey, "Id", student.Id + 1, When.NotExists); + var id_When_NotExists_No = hashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists); Assert.True(id_When_NotExists_No); - var id_When_NotExists_Yes = hashStudy.HashSet(redisKey, "Id", student.Id + 1, When.NotExists); + var id_When_NotExists_Yes = hashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.NotExists); Assert.False(id_When_NotExists_Yes); - var id_When_Always_Exists = hashStudy.HashSet(redisKey, "Id", student.Id + 1, When.Always); + var id_When_Always_Exists = hashStudy.HashSet(redisKey, "Id", defaultStudent.Id + 1, When.Always); Assert.False(id_When_Always_Exists); - var id_When_Always_NotExists = hashStudy.HashSet(redisKey, "Id4", student.Id + 1, When.Always); + var id_When_Always_NotExists = hashStudy.HashSet(redisKey, "Id4", defaultStudent.Id + 1, When.Always); Assert.True(id_When_Always_NotExists); } @@ -122,14 +139,14 @@ namespace RedisStudyTest /// 添加一个默认学生 测试 /// [Fact] - public void AddStudentTest() + public void HashSetAddStudentTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; var studentEntries = new HashEntry[] { new HashEntry("Id",1), - new HashEntry("Name",student.Name), - new HashEntry("Age",student.Age), + new HashEntry("Name",defaultStudent.Name), + new HashEntry("Age",defaultStudent.Age), }; //插入Sudent @@ -144,7 +161,7 @@ namespace RedisStudyTest /// 添加一组初始化设置的学生 测试 /// [Fact] - public void AddStudentsTest() + public void HashSetAddGroupStudentTest() { foreach (var temp in students) { @@ -163,118 +180,277 @@ namespace RedisStudyTest //设置过期 redisDatabase.KeyExpire(redisKey, TimeSpan.FromSeconds(keyExpireSeconds)); } - } + //清理删除 + foreach (var temp in students) + { + redisDatabase.KeyDelete(preHashKey + temp.Id); + } + } /// - /// 添加或更新字段 测试 + /// 设置一个哈希字段 测试 /// [Fact] - public void SetStudentTest() + public void HashSetHashfieldTest() { - Assert.True(hashStudy.HashSet(preHashKey + student.Id, "Id", student.Id)); - Assert.False(hashStudy.HashSet(preHashKey + student.Id, "Id", student.Id)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Id", defaultStudent.Id)); + Assert.False(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Id", defaultStudent.Id)); - Assert.True(hashStudy.HashSet(preHashKey + student.Id, "Name", student.Name)); - Assert.False(hashStudy.HashSet(preHashKey + student.Id, "Name", student.Name)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Name", defaultStudent.Name)); + Assert.False(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Name", defaultStudent.Name)); - Assert.True(hashStudy.HashSet(preHashKey + student.Id, "Age", student.Age)); - Assert.False(hashStudy.HashSet(preHashKey + student.Id, "Age", student.Age)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Age", defaultStudent.Age)); + Assert.False(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Age", defaultStudent.Age)); } /// - /// 添加或更新字段 测试 + /// 设置一组哈希字段 测试 /// [Fact] - public void SetStudentTest2() + public void HashSetGroupHashfieldTest() { - Assert.True(hashStudy.HashSet(preHashKey + student.Id, "Id", student.Id)); - Assert.False(hashStudy.HashSet(preHashKey + student.Id, "Id", student.Id + 1)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Id", defaultStudent.Id)); + Assert.False(hashStudy.HashSet(preHashKey + defaultStudent.Id, "Id", defaultStudent.Id + 1)); - var entrys=new HashEntry[] + var entrys = new HashEntry[] { - new HashEntry("Name", student.Name), - new HashEntry("Age", student.Age), + new HashEntry("Name", defaultStudent.Name), + new HashEntry("Age", defaultStudent.Age), }; var entrys2 = new HashEntry[] { - new HashEntry("Name", student.Name+"2"), - new HashEntry("Age", student.Age+1), + new HashEntry("Name", defaultStudent.Name+"2"), + new HashEntry("Age", defaultStudent.Age+1), }; - Assert.True(hashStudy.HashSet(preHashKey + student.Id, entrys)); - Assert.True(hashStudy.HashSet(preHashKey + student.Id, entrys2)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, entrys)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, entrys2)); } /// - /// 特例:Hash表键名为""(空字符串) - /// 结果:添加或更新操作能成功,但是字段值插入不进去。 + /// 特例测试:给key为空的哈希 设置字段 + /// 结 果:添加或更新操作能成功,但是字段值插入不进去。 /// [Fact] - public void SetStudentEmptyKeyTest() - { + public void HashSetForEmptyKeyTest() + { Assert.True(hashStudy.HashSet(string.Empty, "Name", "wanggaofeng")); redisDatabase.KeyDelete(string.Empty); } /// - /// 特例:Hash表,字段名为""(空字符串) - /// 结果:添加或更新操作正常,只是字段键名为"" + /// 特例测试:给字段名为空串的哈希 设置字段 + /// 结 果:添加或更新操作正常,只是字段键名为"" /// [Fact] - public void SetStudentEmptyFieldTest() + public void HashSetForEmptyFieldTest() { - Assert.True(hashStudy.HashSet(preHashKey + student.Id, "", student.Id)); - Assert.False(hashStudy.HashSet(preHashKey + student.Id, "", student.Id+1)); + Assert.True(hashStudy.HashSet(preHashKey + defaultStudent.Id, "", defaultStudent.Id)); + Assert.False(hashStudy.HashSet(preHashKey + defaultStudent.Id, "", defaultStudent.Id + 1)); - redisDatabase.KeyDelete(preHashKey + student.Id); + redisDatabase.KeyDelete(preHashKey + defaultStudent.Id); + } + #endregion + + #region HashDecrement + + /// + /// 字段值不是数字时,异常 + /// 原注释:字段不为数据字,则改为数字 + /// 实际执行:抛出异常,不知道是原注释错误,还是其它原因 + /// + [Fact] + public void HashDecrementExceptionTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + Assert.True(hashStudy.HashSet(redisKey, "Name", "wanggaofeng")); + Assert.Throws(() => hashStudy.HashDecrement(redisKey, "Name", 1)); } + /// + /// 哈希表不存在 + /// 则先创建哈希表,再添加值为0的字段,然后执行自减操作 + /// [Fact] - public void HashDecrement() + public void HashDecrementHashKeyTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; - //Key不存在,则新创建之 + //Key不存在,先创建哈希表,再添加值为0的字段,然后执行自减操作 Assert.Equal(-1, hashStudy.HashDecrement(redisKey, "Id", 1)); + + //存在,直接自减 Assert.Equal(-1, hashStudy.HashGet(redisKey, "Id")); + } + + /// + /// 自减字段不存在 + /// 先添加字段,值设为0,然后执行自减操作 + /// + [Fact] + public void HashDecrementHashFieldTest() + { + string redisKey = preHashKey + defaultStudent.Id; //字段不存在,则创建之 Assert.Equal(-1, hashStudy.HashDecrement(redisKey, "Age", 1)); Assert.Equal(-1, hashStudy.HashGet(redisKey, "Age")); + } + + /// + /// 自减负数,则自增 + /// + [Fact] + public void HashDecrementMinusTest() + { + string redisKey = preHashKey + defaultStudent.Id; - //字段不为数据字,则改为数字 - //注意:是否原注释错误?,因为实际执行抛出异常,而不是操作前改为0 - Assert.True(hashStudy.HashSet(redisKey, "Name","wanggaofeng")); - Assert.Throws(()=>hashStudy.HashDecrement(redisKey, "Name", 1)); - //Assert.Equal(-1, hashStudy.HashGet(redisKey, "Name")); + //自减负数时,则自增 + Assert.Equal(2, hashStudy.HashDecrement(redisKey, "Age", -2)); + } + + /// + /// 自减整数 + /// + [Fact] + public void HashDecrementByIntTest() + { + string redisKey = preHashKey + defaultStudent.Id; //字段减少1 - Assert.Equal(-2, hashStudy.HashDecrement(redisKey, "Age", 1)); - //字段减少 - Assert.Equal(-4, hashStudy.HashDecrement(redisKey, "Age", 2)); + Assert.Equal(-1, hashStudy.HashDecrement(redisKey, "Age", 1)); + //字段减少2 + Assert.Equal(-3, hashStudy.HashDecrement(redisKey, "Age", 2)); + } - //增加负数时,啥情况 - Assert.Equal(-2, hashStudy.HashDecrement(redisKey, "Age", -2)); + /// + /// 自减浮点数 + /// 断言应该用精度值在一个小范围内 + /// + [Fact] + public void HashDecrementByDoubleTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + //新字段时,可以用相等比较 + var dec = hashStudy.HashDecrement(redisKey, "Age", 2.1); + var absDec = Math.Abs(-2.1 - dec); + Assert.Equal(0, absDec); + + //已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围 + dec = hashStudy.HashDecrement(redisKey, "Age", 2.5); + absDec = Math.Abs(-4.6 - dec); + Assert.True(absDec < 0.01); } - #endregion + #endregion HashIncrement + + #region HashIncrement + /// + /// 字段值不是数字时,异常 + /// 原注释:字段不为数据字,则改为数字 + /// 实际执行:抛出异常,不知道是原注释错误,还是其它原因 + /// + [Fact] + public void HashIncrementExceptionTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + Assert.True(hashStudy.HashSet(redisKey, "Name", "wanggaofeng")); + Assert.Throws(() => hashStudy.HashIncrement(redisKey, "Name", 1)); + } + + /// + /// 哈希表不存在 + /// 则先创建哈希表,再添加值为0的字段,然后执行自增操作 + /// + [Fact] + public void HashIncrementHashKeyTest() + { + string redisKey = preHashKey + defaultStudent.Id; - #region 获取 + //Key不存在,先创建哈希表,再添加值为0的字段,然后执行自减操作 + Assert.Equal(1, hashStudy.HashIncrement(redisKey, "Id", 1)); + Assert.Equal(1, hashStudy.HashGet(redisKey, "Id")); + } + + /// + /// 自增字段不存在 + /// 先添加字段,值设为0,然后执行自增操作 + /// + [Fact] + public void HashIncrementHashFieldTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + //字段不存在,则创建之 + Assert.Equal(1, hashStudy.HashIncrement(redisKey, "Age", 1)); + Assert.Equal(1, hashStudy.HashGet(redisKey, "Age")); + } + /// + /// 自增负数,则自减 + /// + [Fact] + public void HashIncrementMinusTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + //自增负数时,则自减 + Assert.Equal(-2, hashStudy.HashIncrement(redisKey, "Age", -2)); + } + + /// + /// 自增整数 + /// + [Fact] + public void HashIncrementByIntTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + //字段减少1 + Assert.Equal(1, hashStudy.HashIncrement(redisKey, "Age", 1)); + //字段减少2 + Assert.Equal(3, hashStudy.HashIncrement(redisKey, "Age", 2)); + } + + /// + /// 自增浮点数 + /// 断言应该用精度值在一个小范围内 + /// + [Fact] + public void HashIncrementByDoubleTest() + { + string redisKey = preHashKey + defaultStudent.Id; + + //新字段时,可以用相等比较 + var dec = hashStudy.HashIncrement(redisKey, "Age", 2.1); + var absDec = Math.Abs(2.1 - dec); + Assert.Equal(0, absDec); + + //已经存在的,浮点数,不使用相等比较,而改用两值相差一定的小范围 + dec = hashStudy.HashIncrement(redisKey, "Age", 2.5); + absDec = Math.Abs(4.6 - dec); + Assert.True(absDec < 0.01); + } + #endregion + + #region HashGetAll /// /// 获取一个学生 /// [Fact] - public void GetOneSutdentTest() + public void HashGetAllTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; var studentEntries = new HashEntry[] { new HashEntry("Id",1), - new HashEntry("Name",student.Name), - new HashEntry("Age",student.Age), + new HashEntry("Name",defaultStudent.Name), + new HashEntry("Age",defaultStudent.Age), }; //插入Sudent @@ -287,59 +463,183 @@ namespace RedisStudyTest Student myStudent = new Student() { - Id = (int)entries.FirstOrDefault(e=>e.Name=="Id").Value, + 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==student.Id && myStudent.Name==student.Name && myStudent.Age==student.Age); + Assert.True(myStudent.Id == defaultStudent.Id && myStudent.Name == defaultStudent.Name && myStudent.Age == defaultStudent.Age); + + } + #endregion + #region HashGet + + /// + /// 哈希表不存在时,获取字段值 + /// + [Fact] + public void HashGetNotKkeyTest() + { + string redisKey = preHashKey + defaultStudent.Id; + var result = hashStudy.HashGet(redisKey, "Id"); + + Assert.False(result.HasValue); } + /// + /// 字段不存在时,获取字段值 + /// [Fact] - public void GetId() + public void HashGetNotHashfieldTest() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; - Assert.NotEqual(student.Id, hashStudy.HashGet(redisKey,"Id")); + hashStudy.HashIncrement(redisKey, "Id", 1); + + var result = hashStudy.HashGet(redisKey, "Name"); + + Assert.False(result.HasValue); + } + [Fact] + public void HashGetTest() + { + string redisKey = preHashKey + defaultStudent.Id; AddDefaultStudent(); + Assert.Equal(1, hashStudy.HashGet(redisKey, "Id")); + Assert.Equal(defaultStudent.Name, hashStudy.HashGet(redisKey, "Name")); + Assert.Equal(defaultStudent.Age, hashStudy.HashGet(redisKey, "Age")); } + #endregion + + #region HashKeys + + /// + /// 哈希不存在时,获取所有字段的Key + /// [Fact] - public void GetName() + public void HashKeysNotKeyTest() { - string redisKey = preHashKey + student.Id; + RedisValue[] keys = hashStudy.HashKeys(defaultHashKey); + + Assert.NotNull(keys); + Assert.Empty(keys); + } - Assert.NotEqual(student.Name, hashStudy.HashGet(redisKey, "Name").ToString()); + /// + /// 获取哈希所有字段的Key + /// + [Fact] + public void HashKeys() + { AddDefaultStudent(); - Assert.Equal(student.Name, hashStudy.HashGet(redisKey, "Name")); + + RedisValue[] keys = hashStudy.HashKeys(defaultHashKey); + Assert.NotEmpty(keys); + + Assert.Contains("Id", keys); + Assert.Contains("Name", keys); + Assert.Contains("Age", keys); } + #endregion + #region HashValues + /// + /// 哈希不存在时,获取所有字段的Key + /// [Fact] - public void GetAge() + public void HashValuesNotKeyTest() { - string redisKey = preHashKey + student.Id; + RedisValue[] keys = hashStudy.HashValues(defaultHashKey); - Assert.NotEqual(student.Age, hashStudy.HashGet(redisKey, "Age")); + Assert.NotNull(keys); + Assert.Empty(keys); + } + /// + /// 获取哈希所有字段的Key + /// + + [Fact] + public void HashValues() + { AddDefaultStudent(); - Assert.Equal(student.Age, hashStudy.HashGet(redisKey, "Age")); + + RedisValue[] values = hashStudy.HashValues(defaultHashKey); + 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() + { + string redisKey = preHashKey + defaultStudent.Id; + var result = hashStudy.HashLength(redisKey); + + Assert.Equal(0, result); + } + + /// + /// 获取哈希字段数 + /// + [Fact] + public void HashLengthTest() + { + string redisKey = preHashKey + defaultStudent.Id; + AddDefaultStudent(); + + var result = hashStudy.HashLength(redisKey); + + Assert.Equal(3, result); + } + + #endregion + + #region HashScan + + /// + /// 哈希不存在时,HashScan + /// + [Fact] + public void HashScanNotKey() + { + var hashEntrys= hashStudy.HashScan(defaultHashKey); + + var num = hashEntrys.Count(); + Assert.Equal(0, num); + + var entryList = hashEntrys.ToList(); + + Assert.Empty(entryList); + } + #endregion + + #region HashExists /// /// 指定字段是否存在 /// [Fact] - public void ExistStudent() + public void HashExists() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; var studentEntries = new HashEntry[] { new HashEntry("Id",1), - new HashEntry("Name",student.Name), + new HashEntry("Name",defaultStudent.Name), }; //插入Sudent @@ -350,16 +650,62 @@ namespace RedisStudyTest Assert.True(hashStudy.HashExists(redisKey, "Name")); Assert.False(hashStudy.HashExists(redisKey, "Age")); } + #endregion + + #region HashDelete + /// + /// 哈希不存在时,删除哈希字段 + /// + [Fact] + public void HashDeleteNotKeyTest() + { + string redisKey = preHashKey + defaultStudent.Id; + var hashDeleteResult = hashStudy.HashDelete(redisKey, "FieldFirst"); + + Assert.False(hashDeleteResult); + } + + /// + /// 删除不存在的哈希字段 + /// + [Fact] + public void HashDeleteNotFieldTest() + { + string redisKey = preHashKey + defaultStudent.Id; + hashStudy.HashIncrement(redisKey, "Id",1); + + var hashDeleteResult = hashStudy.HashDelete(redisKey, "Name"); + Assert.False(hashDeleteResult); + } + + /// + /// 删除哈希字段 + /// + [Fact] + public void HashDeleteTest() + { + string redisKey = preHashKey + defaultStudent.Id; + AddDefaultStudent(); + + var hashDeleteResult = hashStudy.HashDelete(redisKey, "Id"); + Assert.True(hashDeleteResult); + + hashDeleteResult = hashStudy.HashDelete(redisKey, "Name"); + Assert.True(hashDeleteResult); + + hashDeleteResult = hashStudy.HashDelete(redisKey, "Age"); + Assert.True(hashDeleteResult); + } #endregion - #region 删除学生 + #region HashKeyDelete /// /// 删除学生 /// [Fact] - public void DeleteStudent() + public void KeyDeleteTest() { Assert.False(redisDatabase.KeyDelete(preHashKey + "-2000")); } @@ -374,34 +720,31 @@ namespace RedisStudyTest DeleteExitsStudents(); } + #region 辅助方法 /// /// 删除Redis中的测试学生 /// private void DeleteExitsStudents() { - if (student != null) + if (defaultStudent != null) { - redisDatabase.KeyDelete(preHashKey + student.Id); - } - - foreach (var temp in students) - { - redisDatabase.KeyDelete(preHashKey + temp.Id); + redisDatabase.KeyDelete(preHashKey + defaultStudent.Id); } } private void AddDefaultStudent() { - string redisKey = preHashKey + student.Id; + string redisKey = preHashKey + defaultStudent.Id; var studentEntries = new HashEntry[] { new HashEntry("Id",1), - new HashEntry("Name",student.Name), - new HashEntry("Age",student.Age), + new HashEntry("Name",defaultStudent.Name), + new HashEntry("Age",defaultStudent.Age), }; //插入Sudent var addHash = hashStudy.HashSet(redisKey, studentEntries); } + #endregion } } diff --git a/RedisStuy/RedisHashStudy.cs b/RedisStuy/RedisHashStudy.cs index 9d60594..76b7f5d 100644 --- a/RedisStuy/RedisHashStudy.cs +++ b/RedisStuy/RedisHashStudy.cs @@ -23,7 +23,7 @@ namespace RedisStuy #endregion /// - /// 整数减少hash中,指定列的值 + /// 整数自减hash字段 /// key不存在,则创建一个持有哈希的新密钥。 /// hashField字段不存在或持有不能被解释为整数的字符串,则在执行前将该值设置为0 ///