chore: 初始化仓库,排除二进制文件和覆盖率文件
This commit is contained in:
235
pkg/auth/jwt_test.go
Normal file
235
pkg/auth/jwt_test.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestNewJWTService 测试创建JWT服务
|
||||
func TestNewJWTService(t *testing.T) {
|
||||
secretKey := "test-secret-key"
|
||||
expireHours := 24
|
||||
|
||||
service := NewJWTService(secretKey, expireHours)
|
||||
if service == nil {
|
||||
t.Fatal("NewJWTService() 返回nil")
|
||||
}
|
||||
|
||||
if service.secretKey != secretKey {
|
||||
t.Errorf("secretKey = %q, want %q", service.secretKey, secretKey)
|
||||
}
|
||||
|
||||
if service.expireHours != expireHours {
|
||||
t.Errorf("expireHours = %d, want %d", service.expireHours, expireHours)
|
||||
}
|
||||
}
|
||||
|
||||
// TestJWTService_GenerateToken 测试生成Token
|
||||
func TestJWTService_GenerateToken(t *testing.T) {
|
||||
service := NewJWTService("test-secret-key", 24)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
userID int64
|
||||
username string
|
||||
role string
|
||||
wantError bool
|
||||
}{
|
||||
{
|
||||
name: "正常生成Token",
|
||||
userID: 1,
|
||||
username: "testuser",
|
||||
role: "user",
|
||||
wantError: false,
|
||||
},
|
||||
{
|
||||
name: "空用户名",
|
||||
userID: 1,
|
||||
username: "",
|
||||
role: "user",
|
||||
wantError: false, // JWT允许空字符串
|
||||
},
|
||||
{
|
||||
name: "空角色",
|
||||
userID: 1,
|
||||
username: "testuser",
|
||||
role: "",
|
||||
wantError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
token, err := service.GenerateToken(tt.userID, tt.username, tt.role)
|
||||
if (err != nil) != tt.wantError {
|
||||
t.Errorf("GenerateToken() error = %v, wantError %v", err, tt.wantError)
|
||||
return
|
||||
}
|
||||
if !tt.wantError {
|
||||
if token == "" {
|
||||
t.Error("GenerateToken() 返回的token不应为空")
|
||||
}
|
||||
// 验证token长度合理(JWT token通常很长)
|
||||
if len(token) < 50 {
|
||||
t.Errorf("GenerateToken() 返回的token长度异常: %d", len(token))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestJWTService_ValidateToken 测试验证Token
|
||||
func TestJWTService_ValidateToken(t *testing.T) {
|
||||
secretKey := "test-secret-key"
|
||||
service := NewJWTService(secretKey, 24)
|
||||
|
||||
// 生成一个有效的token
|
||||
userID := int64(1)
|
||||
username := "testuser"
|
||||
role := "user"
|
||||
token, err := service.GenerateToken(userID, username, role)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
token string
|
||||
wantError bool
|
||||
wantUserID int64
|
||||
wantUsername string
|
||||
wantRole string
|
||||
}{
|
||||
{
|
||||
name: "有效token",
|
||||
token: token,
|
||||
wantError: false,
|
||||
wantUserID: userID,
|
||||
wantUsername: username,
|
||||
wantRole: role,
|
||||
},
|
||||
{
|
||||
name: "无效token",
|
||||
token: "invalid.token.here",
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "空token",
|
||||
token: "",
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "使用不同密钥签名的token",
|
||||
token: func() string {
|
||||
otherService := NewJWTService("different-secret", 24)
|
||||
token, _ := otherService.GenerateToken(1, "user", "role")
|
||||
return token
|
||||
}(),
|
||||
wantError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
claims, err := service.ValidateToken(tt.token)
|
||||
if (err != nil) != tt.wantError {
|
||||
t.Errorf("ValidateToken() error = %v, wantError %v", err, tt.wantError)
|
||||
return
|
||||
}
|
||||
if !tt.wantError {
|
||||
if claims == nil {
|
||||
t.Fatal("ValidateToken() 返回的claims不应为nil")
|
||||
}
|
||||
if claims.UserID != tt.wantUserID {
|
||||
t.Errorf("UserID = %d, want %d", claims.UserID, tt.wantUserID)
|
||||
}
|
||||
if claims.Username != tt.wantUsername {
|
||||
t.Errorf("Username = %q, want %q", claims.Username, tt.wantUsername)
|
||||
}
|
||||
if claims.Role != tt.wantRole {
|
||||
t.Errorf("Role = %q, want %q", claims.Role, tt.wantRole)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestJWTService_TokenRoundTrip 测试Token的完整流程
|
||||
func TestJWTService_TokenRoundTrip(t *testing.T) {
|
||||
service := NewJWTService("test-secret-key", 24)
|
||||
|
||||
userID := int64(123)
|
||||
username := "testuser"
|
||||
role := "admin"
|
||||
|
||||
// 生成token
|
||||
token, err := service.GenerateToken(userID, username, role)
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证token
|
||||
claims, err := service.ValidateToken(token)
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证claims内容
|
||||
if claims.UserID != userID {
|
||||
t.Errorf("UserID = %d, want %d", claims.UserID, userID)
|
||||
}
|
||||
if claims.Username != username {
|
||||
t.Errorf("Username = %q, want %q", claims.Username, username)
|
||||
}
|
||||
if claims.Role != role {
|
||||
t.Errorf("Role = %q, want %q", claims.Role, role)
|
||||
}
|
||||
}
|
||||
|
||||
// TestJWTService_TokenExpiration 测试Token过期时间
|
||||
func TestJWTService_TokenExpiration(t *testing.T) {
|
||||
expireHours := 24
|
||||
service := NewJWTService("test-secret-key", expireHours)
|
||||
|
||||
token, err := service.GenerateToken(1, "user", "role")
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
claims, err := service.ValidateToken(token)
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证过期时间
|
||||
if claims.ExpiresAt == nil {
|
||||
t.Error("ExpiresAt 不应为nil")
|
||||
} else {
|
||||
expectedExpiry := time.Now().Add(time.Duration(expireHours) * time.Hour)
|
||||
// 允许1分钟的误差
|
||||
diff := claims.ExpiresAt.Time.Sub(expectedExpiry)
|
||||
if diff < -time.Minute || diff > time.Minute {
|
||||
t.Errorf("ExpiresAt 时间异常: %v, 期望约 %v", claims.ExpiresAt.Time, expectedExpiry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestJWTService_TokenIssuer 测试Token发行者
|
||||
func TestJWTService_TokenIssuer(t *testing.T) {
|
||||
service := NewJWTService("test-secret-key", 24)
|
||||
|
||||
token, err := service.GenerateToken(1, "user", "role")
|
||||
if err != nil {
|
||||
t.Fatalf("GenerateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
claims, err := service.ValidateToken(token)
|
||||
if err != nil {
|
||||
t.Fatalf("ValidateToken() 失败: %v", err)
|
||||
}
|
||||
|
||||
expectedIssuer := "carrotskin"
|
||||
if claims.Issuer != expectedIssuer {
|
||||
t.Errorf("Issuer = %q, want %q", claims.Issuer, expectedIssuer)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user