移除所有测试代码和测试要求
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m33s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m33s
**变更说明**: - 删除所有 *_test.go 文件(单元测试、集成测试、验收测试、流程测试) - 删除整个 tests/ 目录 - 更新 CLAUDE.md:用"测试禁令"章节替换所有测试要求 - 删除测试生成 Skill (openspec-generate-acceptance-tests) - 删除测试生成命令 (opsx:gen-tests) - 更新 tasks.md:删除所有测试相关任务 **新规范**: - ❌ 禁止编写任何形式的自动化测试 - ❌ 禁止创建 *_test.go 文件 - ❌ 禁止在任务中包含测试相关工作 - ✅ 仅当用户明确要求时才编写测试 **原因**: 业务系统的正确性通过人工验证和生产环境监控保证,测试代码维护成本高于价值。 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,357 +0,0 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/config"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func setupTestRedis(t *testing.T) *redis.Client {
|
||||
var addr, password string
|
||||
testDB := 15
|
||||
|
||||
cfg, err := config.Load()
|
||||
if err != nil {
|
||||
t.Logf("配置加载失败,使用回退配置: %v", err)
|
||||
addr = "localhost:6379"
|
||||
password = ""
|
||||
} else {
|
||||
t.Logf("成功加载配置,Redis 地址: %s:%d", cfg.Redis.Address, cfg.Redis.Port)
|
||||
addr = fmt.Sprintf("%s:%d", cfg.Redis.Address, cfg.Redis.Port)
|
||||
password = cfg.Redis.Password
|
||||
}
|
||||
|
||||
client := redis.NewClient(&redis.Options{
|
||||
Addr: addr,
|
||||
Password: password,
|
||||
DB: testDB,
|
||||
})
|
||||
|
||||
ctx := context.Background()
|
||||
if err := client.Ping(ctx).Err(); err != nil {
|
||||
t.Skipf("Redis 未运行(地址: %s),跳过测试: %v", addr, err)
|
||||
}
|
||||
|
||||
client.FlushDB(ctx)
|
||||
|
||||
t.Cleanup(func() {
|
||||
client.FlushDB(ctx)
|
||||
client.Close()
|
||||
})
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
func init() {
|
||||
if os.Getenv("CONFIG_ENV") == "" {
|
||||
os.Setenv("CONFIG_ENV", "dev")
|
||||
}
|
||||
|
||||
if os.Getenv("CONFIG_PATH") == "" {
|
||||
os.Setenv("CONFIG_PATH", "../../configs/config.dev.yaml")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTokenManager_GenerateTokenPair(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("成功生成 token 对", func(t *testing.T) {
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
ShopID: 10,
|
||||
EnterpriseID: 0,
|
||||
Username: "testuser",
|
||||
Device: "web",
|
||||
IP: "127.0.0.1",
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, accessToken)
|
||||
assert.NotEmpty(t, refreshToken)
|
||||
assert.Len(t, accessToken, 36)
|
||||
assert.Len(t, refreshToken, 36)
|
||||
})
|
||||
|
||||
t.Run("生成的 token 存储在 Redis 中", func(t *testing.T) {
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 2,
|
||||
UserType: 2,
|
||||
Username: "admin",
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
accessKey := "auth:token:" + accessToken
|
||||
refreshKey := "auth:refresh:" + refreshToken
|
||||
|
||||
exists, err := rdb.Exists(ctx, accessKey).Result()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1), exists)
|
||||
|
||||
exists, err = rdb.Exists(ctx, refreshKey).Result()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(1), exists)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_ValidateAccessToken(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
ShopID: 10,
|
||||
EnterpriseID: 0,
|
||||
Username: "testuser",
|
||||
Device: "web",
|
||||
IP: "127.0.0.1",
|
||||
}
|
||||
|
||||
accessToken, _, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("验证有效的 access token", func(t *testing.T) {
|
||||
info, err := tm.ValidateAccessToken(ctx, accessToken)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, info)
|
||||
assert.Equal(t, uint(1), info.UserID)
|
||||
assert.Equal(t, 1, info.UserType)
|
||||
assert.Equal(t, uint(10), info.ShopID)
|
||||
assert.Equal(t, "testuser", info.Username)
|
||||
})
|
||||
|
||||
t.Run("验证无效的 token", func(t *testing.T) {
|
||||
info, err := tm.ValidateAccessToken(ctx, "invalid-token")
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
assert.Contains(t, err.Error(), "无效或过期")
|
||||
})
|
||||
|
||||
t.Run("验证空 token", func(t *testing.T) {
|
||||
info, err := tm.ValidateAccessToken(ctx, "")
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_ValidateRefreshToken(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
Username: "testuser",
|
||||
}
|
||||
|
||||
_, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("验证有效的 refresh token", func(t *testing.T) {
|
||||
info, err := tm.ValidateRefreshToken(ctx, refreshToken)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, info)
|
||||
assert.Equal(t, uint(1), info.UserID)
|
||||
assert.Equal(t, "testuser", info.Username)
|
||||
})
|
||||
|
||||
t.Run("验证无效的 refresh token", func(t *testing.T) {
|
||||
info, err := tm.ValidateRefreshToken(ctx, "invalid-refresh-token")
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_RefreshAccessToken(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
Username: "testuser",
|
||||
Device: "web",
|
||||
IP: "127.0.0.1",
|
||||
}
|
||||
|
||||
oldAccessToken, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("成功刷新 access token", func(t *testing.T) {
|
||||
newAccessToken, err := tm.RefreshAccessToken(ctx, refreshToken)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, newAccessToken)
|
||||
assert.NotEqual(t, oldAccessToken, newAccessToken)
|
||||
|
||||
info, err := tm.ValidateAccessToken(ctx, newAccessToken)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, uint(1), info.UserID)
|
||||
})
|
||||
|
||||
t.Run("使用无效的 refresh token", func(t *testing.T) {
|
||||
newAccessToken, err := tm.RefreshAccessToken(ctx, "invalid-refresh-token")
|
||||
|
||||
assert.Error(t, err)
|
||||
assert.Empty(t, newAccessToken)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_RevokeToken(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
Username: "testuser",
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("成功撤销 access token", func(t *testing.T) {
|
||||
err := tm.RevokeToken(ctx, accessToken)
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := tm.ValidateAccessToken(ctx, accessToken)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
|
||||
t.Run("成功撤销 refresh token", func(t *testing.T) {
|
||||
err := tm.RevokeToken(ctx, refreshToken)
|
||||
require.NoError(t, err)
|
||||
|
||||
info, err := tm.ValidateRefreshToken(ctx, refreshToken)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
|
||||
t.Run("撤销不存在的 token 不报错", func(t *testing.T) {
|
||||
err := tm.RevokeToken(ctx, "non-existent-token")
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_RevokeAllUserTokens(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
Username: "testuser",
|
||||
}
|
||||
|
||||
accessToken1, refreshToken1, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
accessToken2, refreshToken2, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("成功撤销用户所有 token", func(t *testing.T) {
|
||||
err := tm.RevokeAllUserTokens(ctx, 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = tm.ValidateAccessToken(ctx, accessToken1)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = tm.ValidateAccessToken(ctx, accessToken2)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = tm.ValidateRefreshToken(ctx, refreshToken1)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = tm.ValidateRefreshToken(ctx, refreshToken2)
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("撤销不存在用户的 token 不报错", func(t *testing.T) {
|
||||
err := tm.RevokeAllUserTokens(ctx, 9999)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_TokenExpiration(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 1*time.Second, 2*time.Second)
|
||||
ctx := context.Background()
|
||||
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: 1,
|
||||
UserType: 1,
|
||||
Username: "testuser",
|
||||
}
|
||||
|
||||
accessToken, refreshToken, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("Access token 过期后无法验证", func(t *testing.T) {
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
info, err := tm.ValidateAccessToken(ctx, accessToken)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
|
||||
t.Run("Refresh token 过期后无法验证", func(t *testing.T) {
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
info, err := tm.ValidateRefreshToken(ctx, refreshToken)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, info)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTokenManager_ConcurrentAccess(t *testing.T) {
|
||||
rdb := setupTestRedis(t)
|
||||
tm := NewTokenManager(rdb, 24*time.Hour, 7*24*time.Hour)
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("并发生成 token", func(t *testing.T) {
|
||||
done := make(chan bool, 10)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(id int) {
|
||||
tokenInfo := &TokenInfo{
|
||||
UserID: uint(id),
|
||||
UserType: 1,
|
||||
Username: "user",
|
||||
}
|
||||
|
||||
_, _, err := tm.GenerateTokenPair(ctx, tokenInfo)
|
||||
assert.NoError(t, err)
|
||||
done <- true
|
||||
}(i)
|
||||
}
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user