| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // MembershipRepo 仓储集成测试(t_membership 成员关系,登录两步协议支撑)。
- //
- // 依赖 test_helpers_test.go 的 setup/insertFixture;未设置 UNIFIED_TEST_DSN 时跳过。
- package repository
- import (
- "context"
- stderrors "errors"
- "testing"
- apperrors "yuansiwei/unified-backend/internal/infra/errors"
- )
- // TestMembershipRepo_ListByCanonicalUserID 多 membership 按 created_at 升序 / 无 membership 返非 nil 空切片。
- func TestMembershipRepo_ListByCanonicalUserID(t *testing.T) {
- gdb := setup(t)
- ctx := context.Background()
- fx := insertFixture(t, gdb, ctx)
- repo := NewMembershipRepo(gdb)
- t.Run("命中_按created_at升序", func(t *testing.T) {
- list, err := repo.ListByCanonicalUserID(ctx, fx.canonical)
- if err != nil {
- t.Fatalf("ListByCanonicalUserID: %v", err)
- }
- if len(list) != 3 {
- t.Fatalf("期望 3 条 membership,实际 %d", len(list))
- }
- // created_at 升序:instB(academic,-30s) → instA(teacher,-20s) → instA(finance,-10s)
- if list[0].InstitutionID != fx.instB || list[0].Role != "academic" {
- t.Errorf("第 1 条 = (%d, %s),期望 (%d, academic)", list[0].InstitutionID, list[0].Role, fx.instB)
- }
- if list[1].InstitutionID != fx.instA || list[1].Role != "teacher" {
- t.Errorf("第 2 条 = (%d, %s),期望 (%d, teacher)", list[1].InstitutionID, list[1].Role, fx.instA)
- }
- if list[2].InstitutionID != fx.instA || list[2].Role != "finance" {
- t.Errorf("第 3 条 = (%d, %s),期望 (%d, finance)", list[2].InstitutionID, list[2].Role, fx.instA)
- }
- })
- t.Run("无membership_返回非nil空切片", func(t *testing.T) {
- list, err := repo.ListByCanonicalUserID(ctx, fx.other)
- if err != nil {
- t.Fatalf("ListByCanonicalUserID(无 membership 用户): %v", err)
- }
- if list == nil {
- t.Errorf("期望非 nil 空切片(JSON 序列化为 [] 而非 null),实际 nil")
- }
- if len(list) != 0 {
- t.Errorf("期望 0 条,实际 %d", len(list))
- }
- })
- }
- // TestMembershipRepo_GetByUserInstitutionCampus 命中 / 同作用域多角色取最新 / 未命中。
- func TestMembershipRepo_GetByUserInstitutionCampus(t *testing.T) {
- gdb := setup(t)
- ctx := context.Background()
- fx := insertFixture(t, gdb, ctx)
- repo := NewMembershipRepo(gdb)
- t.Run("命中_单角色", func(t *testing.T) {
- // instB 下只有 academic 一条
- m, err := repo.GetByUserInstitutionCampus(ctx, fx.canonical, fx.instB, 0)
- if err != nil {
- t.Fatalf("GetByUserInstitutionCampus(instB): %v", err)
- }
- if m.Role != "academic" {
- t.Errorf("instB role = %q,期望 academic", m.Role)
- }
- })
- t.Run("同作用域多角色_取created_at最新", func(t *testing.T) {
- // instA 下有 teacher(-20s) + finance(-10s),finance 较新 → 应取 finance
- m, err := repo.GetByUserInstitutionCampus(ctx, fx.canonical, fx.instA, 0)
- if err != nil {
- t.Fatalf("GetByUserInstitutionCampus(instA): %v", err)
- }
- if m.Role != "finance" {
- t.Errorf("instA 多角色应取最新(finance),实际 %q", m.Role)
- }
- })
- t.Run("未命中_返回ErrNotFound", func(t *testing.T) {
- // 该用户在 instC(不存在的机构)下无 membership
- instC := int64(999)
- _, err := repo.GetByUserInstitutionCampus(ctx, fx.canonical, instC, 0)
- if !stderrors.Is(err, apperrors.ErrNotFound) {
- t.Fatalf("期望 ErrNotFound,实际 %v", err)
- }
- })
- }
|