| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // UserRepo 仓储集成测试(t_user 主表查询 + 密码惰性升级写回)。
- //
- // 依赖 test_helpers_test.go 的 setup/insertFixture;未设置 UNIFIED_TEST_DSN 时跳过。
- package repository
- import (
- "context"
- stderrors "errors"
- "testing"
- apperrors "yuansiwei/unified-backend/internal/infra/errors"
- "yuansiwei/unified-backend/internal/identity/id"
- identitymodel "yuansiwei/unified-backend/internal/identity/model"
- )
- // TestUserRepo_GetByCanonicalUserID 命中 / 未命中。
- func TestUserRepo_GetByCanonicalUserID(t *testing.T) {
- gdb := setup(t)
- ctx := context.Background()
- fx := insertFixture(t, gdb, ctx)
- repo := NewUserRepo(gdb)
- t.Run("命中", func(t *testing.T) {
- u, err := repo.GetByCanonicalUserID(ctx, fx.canonical)
- if err != nil {
- t.Fatalf("GetByCanonicalUserID 命中: %v", err)
- }
- if u.CanonicalUserID != fx.canonical {
- t.Errorf("返回 canonical_user_id = %q,期望 %q", u.CanonicalUserID, fx.canonical)
- }
- if u.Status != identitymodel.UserStatusActive {
- t.Errorf("status = %q,期望 %q", u.Status, identitymodel.UserStatusActive)
- }
- })
- t.Run("未命中_返回ErrNotFound", func(t *testing.T) {
- _, err := repo.GetByCanonicalUserID(ctx, "00000000000000000000000000")
- if !stderrors.Is(err, apperrors.ErrNotFound) {
- t.Fatalf("期望 ErrNotFound,实际 %v", err)
- }
- })
- }
- // TestUserRepo_UpdatePasswordLazyUpgrade 惰性升级写回(argon2 + salt NULL + hash_version)/ 未命中用户。
- func TestUserRepo_UpdatePasswordLazyUpgrade(t *testing.T) {
- gdb := setup(t)
- ctx := context.Background()
- fx := insertFixture(t, gdb, ctx)
- repo := NewUserRepo(gdb)
- t.Run("命中_升级写回argon2_salt置NULL", func(t *testing.T) {
- // 升级前确认旧值
- u, err := repo.GetByCanonicalUserID(ctx, fx.canonical)
- if err != nil {
- t.Fatalf("升级前取用户: %v", err)
- }
- if u.PasswordHash == nil || *u.PasswordHash != fx.hashOld {
- t.Fatalf("升级前 password_hash = %v,期望 %q", u.PasswordHash, fx.hashOld)
- }
- // 升级写回
- if err := repo.UpdatePasswordLazyUpgrade(ctx, fx.canonical, fx.hashNew); err != nil {
- t.Fatalf("UpdatePasswordLazyUpgrade: %v", err)
- }
- // 断言升级后三列
- u2, err := repo.GetByCanonicalUserID(ctx, fx.canonical)
- if err != nil {
- t.Fatalf("升级后取用户: %v", err)
- }
- if u2.PasswordHash == nil || *u2.PasswordHash != fx.hashNew {
- t.Errorf("升级后 password_hash = %v,期望 %q", u2.PasswordHash, fx.hashNew)
- }
- if u2.PasswordSalt != nil {
- t.Errorf("升级后 password_salt 应为 NULL,实际 %v", *u2.PasswordSalt)
- }
- if u2.HashVersion == nil || *u2.HashVersion != identitymodel.HashVersionArgon2 {
- t.Errorf("升级后 hash_version = %v,期望 argon2", u2.HashVersion)
- }
- })
- t.Run("未命中用户_返回ErrNotFound", func(t *testing.T) {
- // 库里不存在该 ULID 的用户(RowsAffected=0 → ErrNotFound)
- ghost, err := id.NewCanonicalUserID()
- if err != nil {
- t.Fatalf("生成 ghost uid: %v", err)
- }
- if err := repo.UpdatePasswordLazyUpgrade(ctx, ghost, fx.hashNew); !stderrors.Is(err, apperrors.ErrNotFound) {
- t.Fatalf("期望 ErrNotFound,实际 %v", err)
- }
- })
- }
|