feat: Enhance dependency injection and service integration

- Updated main.go to initialize email service and include it in the dependency injection container.
- Refactored handlers to utilize context in service method calls, improving consistency and error handling.
- Introduced new service options for upload, security, and captcha services, enhancing modularity and testability.
- Removed unused repository implementations to streamline the codebase.

This commit continues the effort to improve the architecture by ensuring all services are properly injected and utilized across the application.
This commit is contained in:
lan
2025-12-02 22:52:33 +08:00
parent 792e96b238
commit 034e02e93a
54 changed files with 2305 additions and 2708 deletions

View File

@@ -3,6 +3,7 @@ package service
import (
"carrotskin/internal/model"
"carrotskin/pkg/auth"
"context"
"testing"
"go.uber.org/zap"
@@ -16,8 +17,11 @@ func TestUserServiceImpl_Register(t *testing.T) {
logger := zap.NewNop()
// 初始化Service
// 注意redisClient 传入 nil因为 Register 方法中没有使用 redis
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
// 注意redisClient 和 cacheManager 传入 nil因为 Register 方法中没有使用它们
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
// 测试用例
tests := []struct {
@@ -77,7 +81,7 @@ func TestUserServiceImpl_Register(t *testing.T) {
tt.setupMocks()
}
user, token, err := userService.Register(tt.username, tt.password, tt.email, tt.avatar)
user, token, err := userService.Register(ctx, tt.username, tt.password, tt.email, tt.avatar)
if tt.wantErr {
if err == nil {
@@ -124,7 +128,10 @@ func TestUserServiceImpl_Login(t *testing.T) {
}
userRepo.Create(testUser)
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
tests := []struct {
name string
@@ -163,7 +170,7 @@ func TestUserServiceImpl_Login(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
user, token, err := userService.Login(tt.usernameOrEmail, tt.password, "127.0.0.1", "test-agent")
user, token, err := userService.Login(ctx, tt.usernameOrEmail, tt.password, "127.0.0.1", "test-agent")
if tt.wantErr {
if err == nil {
@@ -202,23 +209,26 @@ func TestUserServiceImpl_BasicGettersAndUpdates(t *testing.T) {
}
userRepo.Create(user)
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
// GetByID
gotByID, err := userService.GetByID(1)
gotByID, err := userService.GetByID(ctx, 1)
if err != nil || gotByID == nil || gotByID.ID != 1 {
t.Fatalf("GetByID 返回不正确: user=%+v, err=%v", gotByID, err)
}
// GetByEmail
gotByEmail, err := userService.GetByEmail("basic@example.com")
gotByEmail, err := userService.GetByEmail(ctx, "basic@example.com")
if err != nil || gotByEmail == nil || gotByEmail.Email != "basic@example.com" {
t.Fatalf("GetByEmail 返回不正确: user=%+v, err=%v", gotByEmail, err)
}
// UpdateInfo
user.Username = "updated"
if err := userService.UpdateInfo(user); err != nil {
if err := userService.UpdateInfo(ctx, user); err != nil {
t.Fatalf("UpdateInfo 失败: %v", err)
}
updated, _ := userRepo.FindByID(1)
@@ -227,7 +237,7 @@ func TestUserServiceImpl_BasicGettersAndUpdates(t *testing.T) {
}
// UpdateAvatar 只需确认不会返回错误(具体字段更新由仓库层保证)
if err := userService.UpdateAvatar(1, "http://example.com/avatar.png"); err != nil {
if err := userService.UpdateAvatar(ctx, 1, "http://example.com/avatar.png"); err != nil {
t.Fatalf("UpdateAvatar 失败: %v", err)
}
}
@@ -247,20 +257,23 @@ func TestUserServiceImpl_ChangePassword(t *testing.T) {
}
userRepo.Create(user)
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
// 原密码正确
if err := userService.ChangePassword(1, "oldpass", "newpass"); err != nil {
if err := userService.ChangePassword(ctx, 1, "oldpass", "newpass"); err != nil {
t.Fatalf("ChangePassword 正常情况失败: %v", err)
}
// 用户不存在
if err := userService.ChangePassword(999, "oldpass", "newpass"); err == nil {
if err := userService.ChangePassword(ctx, 999, "oldpass", "newpass"); err == nil {
t.Fatalf("ChangePassword 应在用户不存在时返回错误")
}
// 原密码错误
if err := userService.ChangePassword(1, "wrong", "another"); err == nil {
if err := userService.ChangePassword(ctx, 1, "wrong", "another"); err == nil {
t.Fatalf("ChangePassword 应在原密码错误时返回错误")
}
}
@@ -279,15 +292,18 @@ func TestUserServiceImpl_ResetPassword(t *testing.T) {
}
userRepo.Create(user)
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
// 正常重置
if err := userService.ResetPassword("reset@example.com", "newpass"); err != nil {
if err := userService.ResetPassword(ctx, "reset@example.com", "newpass"); err != nil {
t.Fatalf("ResetPassword 正常情况失败: %v", err)
}
// 用户不存在
if err := userService.ResetPassword("notfound@example.com", "newpass"); err == nil {
if err := userService.ResetPassword(ctx, "notfound@example.com", "newpass"); err == nil {
t.Fatalf("ResetPassword 应在用户不存在时返回错误")
}
}
@@ -304,15 +320,18 @@ func TestUserServiceImpl_ChangeEmail(t *testing.T) {
userRepo.Create(user1)
userRepo.Create(user2)
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
// 正常修改
if err := userService.ChangeEmail(1, "new@example.com"); err != nil {
if err := userService.ChangeEmail(ctx, 1, "new@example.com"); err != nil {
t.Fatalf("ChangeEmail 正常情况失败: %v", err)
}
// 邮箱被其他用户占用
if err := userService.ChangeEmail(1, "user2@example.com"); err == nil {
if err := userService.ChangeEmail(ctx, 1, "user2@example.com"); err == nil {
t.Fatalf("ChangeEmail 应在邮箱被占用时返回错误")
}
}
@@ -324,7 +343,10 @@ func TestUserServiceImpl_ValidateAvatarURL(t *testing.T) {
jwtService := auth.NewJWTService("secret", 1)
logger := zap.NewNop()
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
ctx := context.Background()
tests := []struct {
name string
@@ -341,7 +363,7 @@ func TestUserServiceImpl_ValidateAvatarURL(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := userService.ValidateAvatarURL(tt.url)
err := userService.ValidateAvatarURL(ctx, tt.url)
if (err != nil) != tt.wantErr {
t.Fatalf("ValidateAvatarURL(%q) error = %v, wantErr=%v", tt.url, err, tt.wantErr)
}
@@ -357,7 +379,8 @@ func TestUserServiceImpl_MaxLimits(t *testing.T) {
logger := zap.NewNop()
// 未配置时走默认值
userService := NewUserService(userRepo, configRepo, jwtService, nil, logger)
cacheManager := NewMockCacheManager()
userService := NewUserService(userRepo, configRepo, jwtService, nil, cacheManager, logger)
if got := userService.GetMaxProfilesPerUser(); got != 5 {
t.Fatalf("GetMaxProfilesPerUser 默认值错误, got=%d", got)
}
@@ -375,4 +398,4 @@ func TestUserServiceImpl_MaxLimits(t *testing.T) {
if got := userService.GetMaxTexturesPerUser(); got != 100 {
t.Fatalf("GetMaxTexturesPerUser 配置值错误, got=%d", got)
}
}
}