package service_test import ( "context" "testing" "time" "github.com/user-management-system/internal/domain" "github.com/user-management-system/internal/service" ) // ============================================================================= // Stats Service Tests - TDD approach // ============================================================================= // mockStatsUserRepo 模拟用户仓储 type mockStatsUserRepo struct { totalUsers int64 activeUsers int64 inactiveUsers int64 lockedUsers int64 disabledUsers int64 newUsersToday int64 } func (m *mockStatsUserRepo) List(ctx context.Context, offset, limit int) ([]*domain.User, int64, error) { return nil, m.totalUsers, nil } func (m *mockStatsUserRepo) ListByStatus(ctx context.Context, status domain.UserStatus, offset, limit int) ([]*domain.User, int64, error) { switch status { case domain.UserStatusActive: return nil, m.activeUsers, nil case domain.UserStatusInactive: return nil, m.inactiveUsers, nil case domain.UserStatusLocked: return nil, m.lockedUsers, nil case domain.UserStatusDisabled: return nil, m.disabledUsers, nil } return nil, 0, nil } func (m *mockStatsUserRepo) ListCreatedAfter(ctx context.Context, since time.Time, offset, limit int) ([]*domain.User, int64, error) { return nil, m.newUsersToday, nil } // mockStatsLoginLogRepo 模拟登录日志仓储 type mockStatsLoginLogRepo struct { successCount int64 failedCount int64 weekCount int64 } func (m *mockStatsLoginLogRepo) CountByResultSince(ctx context.Context, success bool, since time.Time) (int64, error) { if success { return m.successCount, nil } return m.failedCount, nil } func TestStatsService_GetUserStats(t *testing.T) { ctx := context.Background() t.Run("获取用户统计", func(t *testing.T) { userRepo := &mockStatsUserRepo{ totalUsers: 100, activeUsers: 80, inactiveUsers: 10, lockedUsers: 5, disabledUsers: 5, newUsersToday: 3, } loginLogRepo := &mockStatsLoginLogRepo{} svc := service.NewStatsService(userRepo, loginLogRepo) stats, err := svc.GetUserStats(ctx) if err != nil { t.Fatalf("GetUserStats failed: %v", err) } if stats.TotalUsers != 100 { t.Errorf("期望 TotalUsers=100, 得到 %d", stats.TotalUsers) } if stats.ActiveUsers != 80 { t.Errorf("期望 ActiveUsers=80, 得到 %d", stats.ActiveUsers) } if stats.InactiveUsers != 10 { t.Errorf("期望 InactiveUsers=10, 得到 %d", stats.InactiveUsers) } if stats.LockedUsers != 5 { t.Errorf("期望 LockedUsers=5, 得到 %d", stats.LockedUsers) } if stats.DisabledUsers != 5 { t.Errorf("期望 DisabledUsers=5, 得到 %d", stats.DisabledUsers) } }) } func TestStatsService_GetDashboardStats(t *testing.T) { ctx := context.Background() t.Run("获取仪表盘统计", func(t *testing.T) { userRepo := &mockStatsUserRepo{ totalUsers: 50, activeUsers: 40, inactiveUsers: 5, lockedUsers: 3, disabledUsers: 2, newUsersToday: 2, } loginLogRepo := &mockStatsLoginLogRepo{ successCount: 100, failedCount: 10, weekCount: 500, } svc := service.NewStatsService(userRepo, loginLogRepo) stats, err := svc.GetDashboardStats(ctx) if err != nil { t.Fatalf("GetDashboardStats failed: %v", err) } if stats.Users.TotalUsers != 50 { t.Errorf("期望 Users.TotalUsers=50, 得到 %d", stats.Users.TotalUsers) } if stats.Logins.LoginsTodaySuccess != 100 { t.Errorf("期望 LoginsTodaySuccess=100, 得到 %d", stats.Logins.LoginsTodaySuccess) } if stats.Logins.LoginsTodayFailed != 10 { t.Errorf("期望 LoginsTodayFailed=10, 得到 %d", stats.Logins.LoginsTodayFailed) } }) }