Files
gochat/internal/app/redis_test.go_BAK
T
2026-06-04 15:44:48 +08:00

226 lines
5.6 KiB
Plaintext

package app
import (
"context"
"testing"
"github.com/alicebob/miniredis/v2"
"github.com/gochat/gochat/internal/config"
"github.com/redis/go-redis/v9"
)
// TestParseRedisURL 测试 parseRedisURL 函数的各种 URL 格式解析
func TestParseRedisURL(t *testing.T) {
tests := []struct {
name string // 测试用例名称
urlStr string // 输入的 Redis URL
wantErr bool // 是否期望返回错误
want *redis.Options // 期望的解析结果(仅检查关键字段)
}{
{
name: "标准Redis URL - host:port/db",
urlStr: "redis://localhost:6379/0",
wantErr: false,
want: &redis.Options{
Addr: "localhost:6379",
DB: 0,
},
},
{
name: "带用户名密码的Redis URL",
urlStr: "redis://user:password@localhost:6379/1",
wantErr: false,
want: &redis.Options{
Addr: "localhost:6379",
DB: 1,
Username: "user",
Password: "password",
},
},
{
name: "仅密码的Redis URL",
urlStr: "redis://:secretpass@localhost:6379/2",
wantErr: false,
want: &redis.Options{
Addr: "localhost:6379",
DB: 2,
Password: "secretpass",
},
},
{
name: "简单host:port格式 - 回退解析",
urlStr: "redis://myhost:6380",
wantErr: false,
want: &redis.Options{
Addr: "myhost:6380",
},
},
{
name: "无效URL - 空字符串",
urlStr: "",
wantErr: true,
},
{
name: "无效URL - 非Redis协议",
urlStr: "http://localhost:6379",
wantErr: true,
},
{
name: "无效URL - 端口不是数字",
urlStr: "redis://localhost:abc",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
opts, err := parseRedisURL(tt.urlStr)
if tt.wantErr {
if err == nil {
t.Errorf("parseRedisURL(%q) 期望返回错误,但未返回错误", tt.urlStr)
}
return
}
if err != nil {
t.Errorf("parseRedisURL(%q) 未期望返回错误,但返回了: %v", tt.urlStr, err)
return
}
// 检查关键字段
if opts.Addr != tt.want.Addr {
t.Errorf("parseRedisURL(%q) Addr = %q, 期望 %q", tt.urlStr, opts.Addr, tt.want.Addr)
}
if opts.DB != tt.want.DB {
t.Errorf("parseRedisURL(%q) DB = %d, 期望 %d", tt.urlStr, opts.DB, tt.want.DB)
}
if tt.want.Username != "" && opts.Username != tt.want.Username {
t.Errorf("parseRedisURL(%q) Username = %q, 期望 %q", tt.urlStr, opts.Username, tt.want.Username)
}
if tt.want.Password != "" && opts.Password != tt.want.Password {
t.Errorf("parseRedisURL(%q) Password = %q, 期望 %q", tt.urlStr, opts.Password, tt.want.Password)
}
})
}
}
// TestNewRedisClient_Success 使用 miniredis 模拟 Redis 服务,测试成功连接
func TestNewRedisClient_Success(t *testing.T) {
// 启动 miniredis 模拟服务器
mr, err := miniredis.Run()
if err != nil {
t.Fatalf("启动 miniredis 失败: %v", err)
}
defer mr.Close()
cfg := &config.RedisConfig{
URL: "redis://" + mr.Addr(),
}
client, err := NewRedisClient(cfg)
if err != nil {
t.Fatalf("NewRedisClient 返回了意外的错误: %v", err)
}
defer client.Close()
// 验证客户端可以正常执行命令
ctx := context.Background()
val, err := client.Set(ctx, "test_key", "test_value", 0).Result()
if err != nil {
t.Errorf("Set 命令执行失败: %v", err)
}
if val != "OK" {
t.Errorf("Set 返回值 = %q, 期望 %q", val, "OK")
}
got, err := client.Get(ctx, "test_key").Result()
if err != nil {
t.Errorf("Get 命令执行失败: %v", err)
}
if got != "test_value" {
t.Errorf("Get 返回值 = %q, 期望 %q", got, "test_value")
}
}
// TestNewRedisClient_SuccessWithPassword 使用 miniredis 测试带密码的成功连接
func TestNewRedisClient_SuccessWithPassword(t *testing.T) {
mr, err := miniredis.Run()
if err != nil {
t.Fatalf("启动 miniredis 失败: %v", err)
}
defer mr.Close()
// 设置 miniredis 密码
mr.RequireAuth("testpassword")
cfg := &config.RedisConfig{
URL: "redis://" + mr.Addr(),
Password: "testpassword",
}
client, err := NewRedisClient(cfg)
if err != nil {
t.Fatalf("NewRedisClient 返回了意外的错误: %v", err)
}
defer client.Close()
// 验证客户端可以正常执行命令
ctx := context.Background()
result, err := client.Ping(ctx).Result()
if err != nil {
t.Errorf("Ping 命令执行失败: %v", err)
}
if result != "PONG" {
t.Errorf("Ping 返回值 = %q, 期望 %q", result, "PONG")
}
}
// TestNewRedisClient_InvalidURL 测试无效 URL 时 NewRedisClient 返回错误
func TestNewRedisClient_InvalidURL(t *testing.T) {
tests := []struct {
name string
url string
}{
{
name: "空字符串URL",
url: "",
},
{
name: "缺少端口的URL",
url: "redis://localhost",
},
{
name: "端口格式错误",
url: "redis://localhost:notaport",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := &config.RedisConfig{
URL: tt.url,
}
client, err := NewRedisClient(cfg)
if err == nil {
client.Close()
t.Errorf("NewRedisClient(url=%q) 期望返回错误,但未返回错误", tt.url)
}
})
}
}
// TestNewRedisClient_ConnectionFailure 测试连接到不可达的 Redis 服务器时返回错误
func TestNewRedisClient_ConnectionFailure(t *testing.T) {
cfg := &config.RedisConfig{
// 使用一个不会存在的端口,确保连接失败
URL: "redis://127.0.0.1:19999",
}
client, err := NewRedisClient(cfg)
if err == nil {
client.Close()
t.Errorf("NewRedisClient 期望连接失败返回错误,但未返回错误")
}
// 期望包含 "failed to connect to Redis" 的错误信息
if err != nil && client != nil {
t.Logf("连接失败返回了预期的错误: %v", err)
}
}