Go gomock测试中mockgen Return方法返回的预期值被意外修改问题
根因分析
这是Go语言切片的基础特性导致的,和gomock的Return实现无关:
- Go的切片本质是一个包含
底层数组指针、长度、容量的结构体,切片作为值传递时,仅复制结构体本身,内部的指针仍指向同一个底层数组。 - 你在测试中直接将
mock_data.Users赋值给expected并传给Return方法,mock返回的切片和expected变量共享同一底层数组。当你在GetUsers方法中修改users[0].Name时,修改直接作用到了共享的底层数组上,因此expected变量的值也会同步变更,最终断言时二者相等,测试误通过。 - 额外隐患:你直接使用全局变量
mock_data.Users,本次测试修改后,所有其他引用该全局变量的测试用例都会被数据污染。
修复方案
可选择以下任意一种方案解决问题:
- 给mock返回值做深拷贝
每次传入Return的参数都是独立的新切片,避免共享底层数组:
// 示例:复制mock_data.Users生成新切片 expected := append([]model.User{}, mock_data.Users...) ds.EXPECT().GetUsers().Return(expected)
如果切片元素包含指针类型,可以手动实现深拷贝逻辑,避免元素内部的指针共享。
- 修改mock数据定义,每次调用生成新实例
把全局的切片变量改成函数,每次调用返回全新的切片,从源头避免数据共享:
// 修改mock_data定义 func GetMockUsers() []model.User { return []model.User{ { ID: 1, Name: "User A", Email: "usera@gmail.com", }, { ID: 2, Name: "User B", Email: "userb@gmail.com", }, } } // 测试中使用 expected := mock_data.GetMockUsers() ds.EXPECT().GetUsers().Return(expected)
- 断言时使用独立的预期值
不要用传给mock的expected变量做断言,提前定义独立的预期结果:
// 提前定义预期返回的结果,不受mock返回值修改影响 want := []model.User{ {ID: 1, Name: "User C", Email: "usera@gmail.com"}, {ID: 2, Name: "User B", Email: "userb@gmail.com"}, } assert.Equal(t, want, users)
修改后测试就会按照预期逻辑运行,当代码修改了返回值时断言会正常失败。
内容的提问来源于stack exchange,提问作者Mohsin Mushtaq
相关产品推荐
相关产品推荐

