Internal error occurred but is skipped: FindTagsByCommitIDs

Files
CamTalk/backend/internal/store/user_test.go

186 lines
4.8 KiB
Go

package store
import (
"context"
"errors"
"testing"
"time"
)
// newUserRepo 返回一个可测试的 UserRepository 实现。
// 如需测试 Pg 实现,可在此替换为连接真实 DB 的版本。
func newUserRepo() UserRepository {
return NewMemUserRepository()
}
func TestUserRepository_Create(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
id, err := repo.Create(ctx, "alice", "hash123")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
if id == "" {
t.Fatal("expected non-empty ID")
}
// 重复用户名应返回 ErrUsernameTaken
_, err = repo.Create(ctx, "alice", "hash456")
if !errors.Is(err, ErrUsernameTaken) {
t.Fatalf("expected ErrUsernameTaken, got %v", err)
}
}
func TestUserRepository_FindByUsername(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
_, err := repo.Create(ctx, "bob", "hash_bob")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
user, err := repo.FindByUsername(ctx, "bob")
if err != nil {
t.Fatalf("FindByUsername failed: %v", err)
}
if user.Username != "bob" {
t.Fatalf("expected username bob, got %s", user.Username)
}
if user.PasswordHash != "hash_bob" {
t.Fatalf("expected password hash hash_bob, got %s", user.PasswordHash)
}
// 不存在的用户
_, err = repo.FindByUsername(ctx, "nobody")
if !errors.Is(err, ErrUserNotFound) {
t.Fatalf("expected ErrUserNotFound, got %v", err)
}
}
func TestUserRepository_FindByID(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
id, err := repo.Create(ctx, "charlie", "hash_charlie")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
user, err := repo.FindByID(ctx, id)
if err != nil {
t.Fatalf("FindByID failed: %v", err)
}
if user.ID != id {
t.Fatalf("expected ID %s, got %s", id, user.ID)
}
if user.Username != "charlie" {
t.Fatalf("expected username charlie, got %s", user.Username)
}
// 不存在的 ID
_, err = repo.FindByID(ctx, "nonexistent-uuid")
if !errors.Is(err, ErrUserNotFound) {
t.Fatalf("expected ErrUserNotFound, got %v", err)
}
}
func TestUserRepository_RefreshToken(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
userID, err := repo.Create(ctx, "dave", "hash_dave")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
tokenHash := "abc123hash"
expiresAt := time.Now().Add(7 * 24 * time.Hour)
// 保存 token
if err := repo.SaveRefreshToken(ctx, userID, tokenHash, expiresAt); err != nil {
t.Fatalf("SaveRefreshToken failed: %v", err)
}
// 查找 token
foundUserID, err := repo.FindRefreshToken(ctx, tokenHash)
if err != nil {
t.Fatalf("FindRefreshToken failed: %v", err)
}
if foundUserID != userID {
t.Fatalf("expected userID %s, got %s", userID, foundUserID)
}
// 不存在的 token
_, err = repo.FindRefreshToken(ctx, "nonexistent")
if !errors.Is(err, ErrRefreshTokenNotFound) {
t.Fatalf("expected ErrRefreshTokenNotFound, got %v", err)
}
// 删除 token
if err := repo.DeleteRefreshToken(ctx, tokenHash); err != nil {
t.Fatalf("DeleteRefreshToken failed: %v", err)
}
_, err = repo.FindRefreshToken(ctx, tokenHash)
if !errors.Is(err, ErrRefreshTokenNotFound) {
t.Fatalf("expected ErrRefreshTokenNotFound after delete, got %v", err)
}
}
func TestUserRepository_DeleteUserRefreshTokens(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
userID, err := repo.Create(ctx, "eve", "hash_eve")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
// 保存多个 token
for i := 0; i < 3; i++ {
tokenHash := "token_" + string(rune('a'+i))
expiresAt := time.Now().Add(7 * 24 * time.Hour)
if err := repo.SaveRefreshToken(ctx, userID, tokenHash, expiresAt); err != nil {
t.Fatalf("SaveRefreshToken failed: %v", err)
}
}
// 删除用户所有 token
if err := repo.DeleteUserRefreshTokens(ctx, userID); err != nil {
t.Fatalf("DeleteUserRefreshTokens failed: %v", err)
}
// 验证全部删除
for i := 0; i < 3; i++ {
tokenHash := "token_" + string(rune('a'+i))
_, err := repo.FindRefreshToken(ctx, tokenHash)
if !errors.Is(err, ErrRefreshTokenNotFound) {
t.Fatalf("expected ErrRefreshTokenNotFound for token_%c, got %v", 'a'+i, err)
}
}
}
func TestUserRepository_ExpiredRefreshToken(t *testing.T) {
repo := newUserRepo()
ctx := context.Background()
userID, err := repo.Create(ctx, "frank", "hash_frank")
if err != nil {
t.Fatalf("Create failed: %v", err)
}
tokenHash := "expired_token"
expiresAt := time.Now().Add(-1 * time.Hour) // 已过期
if err := repo.SaveRefreshToken(ctx, userID, tokenHash, expiresAt); err != nil {
t.Fatalf("SaveRefreshToken failed: %v", err)
}
// 过期 token 应返回 ErrRefreshTokenNotFound
_, err = repo.FindRefreshToken(ctx, tokenHash)
if !errors.Is(err, ErrRefreshTokenNotFound) {
t.Fatalf("expected ErrRefreshTokenNotFound for expired token, got %v", err)
}
}