You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go单元测试遇user_id主键冲突,如何设置GetCurrentUserID默认值?

解决Go单元测试中user_id主键冲突及控制GetCurrentUserID返回值的问题

核心思路

要在单元测试中让GetCurrentUserID稳定返回1,核心是隔离外部依赖,不让它读取真实用户上下文(比如请求中的用户ID),而是返回预设的固定值。这里提供两种实用方案:

方案一:依赖注入(推荐,代码更易维护)

修改业务代码,将GetCurrentUserID作为依赖传入函数,而非直接调用全局函数:

1. 调整业务代码

// 定义获取用户ID的函数类型
type UserIDGetter func() int

// 修改ToggleTrackToFavourite,接收UserIDGetter作为参数
func ToggleTrackToFavourite(trackID int, getUserID UserIDGetter) error {
    userID := getUserID()
    // 原有的收藏/取消收藏逻辑...
}

// 生产环境用的GetCurrentUserID函数
func GetCurrentUserID() int {
    // 从请求上下文或其他渠道获取真实用户ID
    return realUserID
}

2. 编写单元测试

测试时传入返回固定值1的匿名函数,确保每次调用都拿到相同的user_id:

func TestToggleTrackToFavourite(t *testing.T) {
    // 测试收藏逻辑
    t.Run("add track to favourite", func(t *testing.T) {
        err := ToggleTrackToFavourite(123, func() int { return 1 })
        if err != nil {
            t.Fatalf("expected no error, got %v", err)
        }
        // 验证数据库中是否存在user_id=1、track_id=123的记录
    })

    // 测试取消收藏逻辑
    t.Run("remove track from favourite", func(t *testing.T) {
        // 先插入一条user_id=1、track_id=123的测试数据
        // 调用ToggleTrackToFavourite执行取消操作
        err := ToggleTrackToFavourite(123, func() int { return 1 })
        if err != nil {
            t.Fatalf("expected no error, got %v", err)
        }
        // 验证数据库中该记录已被删除
    })
}

方案二:Mock全局依赖(适合无法修改业务代码的场景)

如果不能改动原有业务代码,可以用Mock库(比如testify/mock)替换全局的用户服务依赖:

1. 定义接口与全局依赖

type UserService interface {
    GetCurrentUserID() int
}

// 生产环境实现
type RealUserService struct{}

func (r *RealUserService) GetCurrentUserID() int {
    return realUserID
}

// 全局依赖,生产环境赋值为RealUserService
var userService UserService = &RealUserService{}

// 原业务函数依赖全局userService
func ToggleTrackToFavourite(trackID int) error {
    userID := userService.GetCurrentUserID()
    // 原有收藏/取消收藏逻辑...
}

2. 编写测试用Mock实现

import "github.com/stretchr/testify/mock"

type MockUserService struct {
    mock.Mock
}

func (m *MockUserService) GetCurrentUserID() int {
    args := m.Called()
    return args.Int(0)
}

func TestToggleTrackToFavourite(t *testing.T) {
    // 替换全局依赖为Mock实例
    mockUserSvc := new(MockUserService)
    userService = mockUserSvc

    // 设置Mock返回固定值1
    mockUserSvc.On("GetCurrentUserID").Return(1)

    // 执行测试
    err := ToggleTrackToFavourite(123)
    if err != nil {
        t.Fatal(err)
    }

    // 验证Mock方法被正确调用
    mockUserSvc.AssertExpectations(t)
}

额外解决主键冲突的注意事项

  • 每次测试前清空测试数据库的收藏表,或使用事务回滚,避免前一次测试的数据残留导致冲突。
  • 确保测试用例之间完全独立,不依赖其他测试的执行顺序。

内容的提问来源于stack exchange,提问作者Galaxy Mail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:52:39