| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- //go:build unit
- package service
- import (
- "context"
- "testing"
- "github.com/stretchr/testify/require"
- )
- // 这些用例锁死"每个入口只声明自己真正要改的列":
- // 任何退回整行回写的改动都会让并发写入被陈旧快照覆盖,并在这里变红。
- func TestUpdateProfile_OnlyDeclaresRequestedColumns(t *testing.T) {
- username := "renamed"
- tests := []struct {
- name string
- req UpdateProfileRequest
- want UserUpdateFields
- }{
- {
- name: "username only",
- req: UpdateProfileRequest{Username: &username},
- want: UserUpdateFields{Username: true},
- },
- {
- name: "notify settings only",
- req: UpdateProfileRequest{BalanceNotifyEnabled: boolPtr(true)},
- want: UserUpdateFields{BalanceNotifySettings: true},
- },
- {
- name: "username and notify threshold",
- req: UpdateProfileRequest{Username: &username, BalanceNotifyThreshold: float64Ptr(1.5)},
- want: UserUpdateFields{Username: true, BalanceNotifySettings: true},
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- repo := &mockUserRepo{getByIDUser: &User{ID: 7, Balance: 0.30, Status: StatusActive}}
- svc := NewUserService(repo, nil, nil, nil)
- _, err := svc.UpdateProfile(context.Background(), 7, tt.req)
- require.NoError(t, err)
- require.Equal(t, []UserUpdateFields{tt.want}, repo.updateFields)
- })
- }
- }
- // 只改头像时用户行没有任何列要写,不应产生一次整行更新。
- func TestUpdateProfile_AvatarOnlySkipsUserRowWrite(t *testing.T) {
- repo := &mockUserRepo{getByIDUser: &User{ID: 7, Balance: 0.30}}
- svc := NewUserService(repo, nil, nil, nil)
- avatar := "https://cdn.example.com/a.png"
- _, err := svc.UpdateProfile(context.Background(), 7, UpdateProfileRequest{AvatarURL: &avatar})
- require.NoError(t, err)
- require.Len(t, repo.upsertAvatarArgs, 1, "avatar must still be stored")
- require.Equal(t, []UserUpdateFields{{}}, repo.updateFields, "no user column should be declared")
- }
- func TestChangePassword_OnlyDeclaresPasswordHash(t *testing.T) {
- user := &User{ID: 7, Balance: 0.30}
- require.NoError(t, user.SetPassword("old-password"))
- repo := &mockUserRepo{getByIDUser: user}
- svc := NewUserService(repo, nil, nil, nil)
- err := svc.ChangePassword(context.Background(), 7, ChangePasswordRequest{
- CurrentPassword: "old-password",
- NewPassword: "new-password",
- })
- require.NoError(t, err)
- require.Equal(t, []UserUpdateFields{{PasswordHash: true}}, repo.updateFields)
- }
- func TestUpdateStatus_OnlyDeclaresStatus(t *testing.T) {
- repo := &mockUserRepo{getByIDUser: &User{ID: 7, Balance: 0.30, Status: StatusActive}}
- svc := NewUserService(repo, nil, nil, nil)
- require.NoError(t, svc.UpdateStatus(context.Background(), 7, StatusDisabled))
- require.Equal(t, []UserUpdateFields{{Status: true}}, repo.updateFields)
- }
|