RedisStudy/RedisStudyTest/RedisHashStudyTest.cs

826 lines
26 KiB
C#

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
{
/// <summary>
/// Redis Hash 类型测试
/// </summary>
[Trait("RedisHash", "All")]
public class RedisHashStudyTest : IDisposable
{
#region 初始化
private readonly ITestOutputHelper testOutput;
private IDatabase redisDatabase = null;
private RedisHashStudy redisHashStudy = null;
private List<Student> defaultStudentList;
private Student defaultStudent = null;
private string preStudentHashKey = "RedisStudy:Student:";
private string defaultStudentHashKey = "";
private int defaultExpireSeconds = 20;
/// <summary>
/// 构造
/// </summary>
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<Student>()
{
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
/// <summary>
/// xUnit输出信息 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact(DisplayName = "HashSet 输出信息测试")]
public void HashSetOutputTest()
{
Assert.True(true);
testOutput.WriteLine("我是xUnit测试输出信息");
}
/// <summary>
/// 参数异常 测试
/// </summary>
[Trait("RedisHash", "HashSet")]
[Fact(DisplayName = "HashSet 异常测试")]
public void HashSetExceptionTest()
{
string redisKey = preStudentHashKey + defaultStudent.Id;
//参数异常测试
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(string.Empty, null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet("", null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(preStudentHashKey + "-1", null));
Assert.Throws<ArgumentNullException>(() => redisHashStudy.HashSet(preStudentHashKey + "-1", new HashEntry[] { }));
}
/// <summary>
/// 参数 When 测试
/// </summary>
[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);
}
/// <summary>
/// 添加一个默认学生 测试
/// </summary>
[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));
}
/// <summary>
/// 添加一组初始化设置的学生 测试
/// </summary>
[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);
}
}
/// <summary>
/// 设置一个哈希字段 测试
/// </summary>
[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));
}
/// <summary>
/// 设置一组哈希字段 测试
/// </summary>
[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));
}
/// <summary>
/// 特例测试给key为string.Empty的哈希 设置字段
/// 结 果:添加或更新操作正常。只是"Redis Desktop Manager"管理工具显示空白
/// </summary>
[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);
}
/// <summary>
/// 特例测试:给字段名为空串的哈希 设置字段
/// 结 果:添加或更新操作正常。只是"Redis Desktop Manager"管理工具显示空白
/// </summary>
[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
/// <summary>
/// 字段值不是数字时,异常
/// 原注释:字段不为数据字,则改为数字
/// 实际执行:抛出异常,不知道是原注释错误,还是其它原因
/// </summary>
[Fact]
public void HashDecrementExceptionTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng"));
Assert.Throws<RedisServerException>(() => redisHashStudy.HashDecrement(defaultStudentHashKey, "Name", 1));
}
/// <summary>
/// 哈希表不存在
/// 则先创建哈希表再添加值为0的字段然后执行自减操作
/// </summary>
[Fact]
public void HashDecrementHashKeyTest()
{
//Key不存在先创建哈希表再添加值为0的字段然后执行自减操作
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Id", 1));
//存在,直接自减
Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Id"));
}
/// <summary>
/// 自减字段不存在
/// 先添加字段值设为0然后执行自减操作
/// </summary>
[Fact]
public void HashDecrementHashFieldTest()
{
//字段不存在,则创建之
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1));
Assert.Equal(-1, redisHashStudy.HashGet(defaultStudentHashKey, "Age"));
}
/// <summary>
/// 自减负数,则自增
/// </summary>
[Fact]
public void HashDecrementMinusTest()
{
//自减负数时,则自增
Assert.Equal(2, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", -2));
}
/// <summary>
/// 自减整数
/// </summary>
[Fact]
public void HashDecrementByIntTest()
{
//字段减少1
Assert.Equal(-1, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 1));
//字段减少2
Assert.Equal(-3, redisHashStudy.HashDecrement(defaultStudentHashKey, "Age", 2));
}
/// <summary>
/// 自减浮点数
/// 断言应该用精度值在一个小范围内
/// </summary>
[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
/// <summary>
/// 字段值不是数字时,异常
/// 原注释:字段不为数据字,则改为数字
/// 实际执行:抛出异常,不知道是原注释错误,还是其它原因
/// </summary>
[Fact]
public void HashIncrementExceptionTest()
{
Assert.True(redisHashStudy.HashSet(defaultStudentHashKey, "Name", "wanggaofeng"));
Assert.Throws<RedisServerException>(() => redisHashStudy.HashIncrement(defaultStudentHashKey, "Name", 1));
}
/// <summary>
/// 哈希表不存在
/// 则先创建哈希表再添加值为0的字段然后执行自增操作
/// </summary>
[Fact]
public void HashIncrementHashKeyTest()
{
//Key不存在先创建哈希表再添加值为0的字段然后执行自减操作
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1));
Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Id"));
}
/// <summary>
/// 自增字段不存在
/// 先添加字段值设为0然后执行自增操作
/// </summary>
[Fact]
public void HashIncrementHashFieldTest()
{
//字段不存在,则创建之
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1));
Assert.Equal(1, redisHashStudy.HashGet(defaultStudentHashKey, "Age"));
}
/// <summary>
/// 自增负数,则自减
/// </summary>
[Fact]
public void HashIncrementMinusTest()
{
//自增负数时,则自减
Assert.Equal(-2, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", -2));
}
/// <summary>
/// 自增整数
/// </summary>
[Fact]
public void HashIncrementByIntTest()
{
//字段减少1
Assert.Equal(1, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 1));
//字段减少2
Assert.Equal(3, redisHashStudy.HashIncrement(defaultStudentHashKey, "Age", 2));
}
/// <summary>
/// 自增浮点数
/// 断言应该用精度值在一个小范围内
/// </summary>
[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
/// <summary>
/// 获取一个学生
/// </summary>
[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
/// <summary>
/// 哈希表不存在时,获取字段值
/// </summary>
[Fact]
public void HashGetNotKkeyTest()
{
var result = redisHashStudy.HashGet(defaultStudentHashKey, "Id");
Assert.False(result.HasValue);
}
/// <summary>
/// 字段不存在时,获取字段值
/// </summary>
[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
/// <summary>
/// 哈希不存在时获取所有字段的Key
/// </summary>
[Fact]
public void HashKeysNotKeyTest()
{
RedisValue[] keys = redisHashStudy.HashKeys(defaultStudentHashKey);
Assert.NotNull(keys);
Assert.Empty(keys);
}
/// <summary>
/// 获取哈希所有字段的Key
/// </summary>
[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
/// <summary>
/// 哈希不存在时获取所有字段的Key
/// </summary>
[Fact]
public void HashValuesNotKeyTest()
{
RedisValue[] keys = redisHashStudy.HashValues(defaultStudentHashKey);
Assert.NotNull(keys);
Assert.Empty(keys);
}
/// <summary>
/// 获取哈希所有字段的Key
/// </summary>
[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
/// <summary>
/// 哈希不存在时,获取字段数
/// </summary>
[Fact]
public void HashLengthNotKeyTest()
{
var result = redisHashStudy.HashLength(defaultStudentHashKey);
Assert.Equal(0, result);
}
/// <summary>
/// 获取哈希字段数
/// </summary>
[Fact]
public void HashLengthTest()
{
AddDefaultStudent();
var result = redisHashStudy.HashLength(defaultStudentHashKey);
Assert.Equal(3, result);
}
#endregion
#region HashScan
/// <summary>
/// 哈希不存在时HashScan
/// </summary>
[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);
}
/// <summary>
/// 简单测试,有单独测试类详细测试
/// </summary>
[Fact]
public void HashScanTest()
{
//插入多列hash
List<HashEntry> hashEntries = new List<HashEntry>();
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<HashEntry> hashEntries = new List<HashEntry>();
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
/// <summary>
/// 指定字段是否存在
/// </summary>
[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
/// <summary>
/// 哈希不存在时,删除哈希字段
/// </summary>
[Fact]
public void HashDeleteNotKeyTest()
{
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "FieldFirst");
Assert.False(hashDeleteResult);
}
/// <summary>
/// 删除不存在的哈希字段
/// </summary>
[Fact]
public void HashDeleteNotFieldTest()
{
redisHashStudy.HashIncrement(defaultStudentHashKey, "Id", 1);
var hashDeleteResult = redisHashStudy.HashDelete(defaultStudentHashKey, "Name");
Assert.False(hashDeleteResult);
}
/// <summary>
/// 删除哈希一个字段
/// </summary>
[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);
}
/// <summary>
/// 删除一组哈希字段
/// </summary>
[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
/// <summary>
/// 删除学生
/// </summary>
[Fact]
public void KeyDeleteTest()
{
Assert.False(redisDatabase.KeyDelete(preStudentHashKey + "-2000"));
}
#endregion
/// <summary>
/// 清理
/// </summary>
public void Dispose()
{
DeleteExitsStudents();
}
#region 辅助方法
/// <summary>
/// 删除Redis中的测试学生
/// </summary>
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
}
}