Files
junhong_cmp_fiber/internal/service/account_audit/service_test.go
huang 80f560df33
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m17s
refactor(account): 统一账号管理API、完善权限检查和操作审计
- 合并 customer_account 和 shop_account 路由到统一的 account 接口
- 新增统一认证接口 (auth handler)
- 实现越权防护中间件和权限检查工具函数
- 新增操作审计日志模型和服务
- 更新数据库迁移 (版本 39: account_operation_log 表)
- 补充集成测试覆盖权限检查和审计日志场景
2026-02-02 17:23:20 +08:00

146 lines
3.4 KiB
Go

package account_audit
import (
"context"
"errors"
"testing"
"time"
"github.com/break/junhong_cmp_fiber/internal/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type MockAccountOperationLogStore struct {
mock.Mock
}
func (m *MockAccountOperationLogStore) Create(ctx context.Context, log *model.AccountOperationLog) error {
args := m.Called(ctx, log)
return args.Error(0)
}
func TestLogOperation_Success(t *testing.T) {
mockStore := new(MockAccountOperationLogStore)
service := NewService(mockStore)
log := &model.AccountOperationLog{
OperatorID: 1,
OperatorType: 2,
OperatorName: "admin",
OperationType: "create",
OperationDesc: "创建账号: testuser",
}
mockStore.On("Create", mock.Anything, log).Return(nil)
ctx := context.Background()
service.LogOperation(ctx, log)
time.Sleep(50 * time.Millisecond)
mockStore.AssertCalled(t, "Create", mock.Anything, log)
}
func TestLogOperation_Failure(t *testing.T) {
mockStore := new(MockAccountOperationLogStore)
service := NewService(mockStore)
log := &model.AccountOperationLog{
OperatorID: 1,
OperatorType: 2,
OperatorName: "admin",
OperationType: "create",
OperationDesc: "创建账号: testuser",
}
mockStore.On("Create", mock.Anything, log).Return(errors.New("database error"))
ctx := context.Background()
assert.NotPanics(t, func() {
service.LogOperation(ctx, log)
})
time.Sleep(50 * time.Millisecond)
mockStore.AssertCalled(t, "Create", mock.Anything, log)
}
func TestLogOperation_NonBlocking(t *testing.T) {
mockStore := new(MockAccountOperationLogStore)
service := NewService(mockStore)
log := &model.AccountOperationLog{
OperatorID: 1,
OperatorType: 2,
OperatorName: "admin",
OperationType: "create",
OperationDesc: "创建账号: testuser",
}
mockStore.On("Create", mock.Anything, log).Run(func(args mock.Arguments) {
time.Sleep(100 * time.Millisecond)
}).Return(nil)
ctx := context.Background()
start := time.Now()
service.LogOperation(ctx, log)
elapsed := time.Since(start)
assert.Less(t, elapsed, 50*time.Millisecond, "LogOperation should return immediately")
time.Sleep(150 * time.Millisecond)
mockStore.AssertCalled(t, "Create", mock.Anything, log)
}
func TestNewService(t *testing.T) {
mockStore := new(MockAccountOperationLogStore)
service := NewService(mockStore)
assert.NotNil(t, service)
assert.Equal(t, mockStore, service.store)
}
func TestLogOperation_WithAllFields(t *testing.T) {
mockStore := new(MockAccountOperationLogStore)
service := NewService(mockStore)
targetAccountID := uint(10)
targetUsername := "targetuser"
targetUserType := 3
requestID := "req-12345"
ipAddress := "127.0.0.1"
userAgent := "Mozilla/5.0"
log := &model.AccountOperationLog{
OperatorID: 1,
OperatorType: 2,
OperatorName: "admin",
TargetAccountID: &targetAccountID,
TargetUsername: &targetUsername,
TargetUserType: &targetUserType,
OperationType: "update",
OperationDesc: "更新账号: targetuser",
BeforeData: model.JSONB{
"username": "oldname",
},
AfterData: model.JSONB{
"username": "newname",
},
RequestID: &requestID,
IPAddress: &ipAddress,
UserAgent: &userAgent,
}
mockStore.On("Create", mock.Anything, log).Return(nil)
ctx := context.Background()
service.LogOperation(ctx, log)
time.Sleep(50 * time.Millisecond)
mockStore.AssertCalled(t, "Create", mock.Anything, log)
}