Go使用testify编写Update方法单元测试时遇未知调用报错
Go中使用Testify测试Update方法失败问题解决
问题背景
在Go项目中使用Testify框架为服务方法编写单元测试时,其他方法测试正常,但Update方法测试失败。原因是Update方法内部调用了同服务的GetByID方法,测试时未正确Mock该调用。
相关代码片段
服务层Update方法实现
func (ts *teamService) Update(team *team.Team) AppError { t, err := ts.TeamRepo.GetByID(team.ID) if err != nil { return err } if t.TeamOwnerID != team.TeamOwnerID { return NewForbiddenError(forbiddenErr) } return ts.TeamRepo.Update(team) }
Mock仓库的Update方法实现
func (t *teamRepoMock) Update(team *team.Team) AppError { args := t.Called(team) if args.Error(0) != nil { return NewNotFoundError(args.Error(0)) } return nil }
测试代码
func TestUpdate(t *testing.T) { _, teamIdGen, playerIdGen := setupConfig() t.Run("Update a team", func(t *testing.T) { teamRepo, _, ts := setupTeamService(teamIdGen, playerIdGen) teamRepo.On("Update", testTeam1).Return(nil) result := ts.Update(testTeam1) assert.Nil(t, result) }) t.Run("Update a team fails", func(t *testing.T) { teamRepo, _, ts := setupTeamService(teamIdGen, playerIdGen) expected := oopsErr teamRepo.On("Update", testTeam1).Return(expected) result := ts.Update(testTeam1) assert.EqualValues(t, expected.Error(), result.Error()) }) }
测试错误信息
--- FAIL: TestUpdate (0.01s) --- FAIL: TestUpdate/Update_a_team (0.01s) panic: assert: mock: I don't know what to return because the method call was unexpected. Either do Mock.On("GetByID").Return(...) first, or remove the GetByID() call. This method was unexpected: GetByID(string) 0: "" at: [/home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service_init_test.go:18 /home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service.go:146 /home/waleem/Desktop/project/eazykhel_server/services/teamservice/team_service_test.go:277] [recovered] panic:
解决方案
1. 检查测试用例数据
错误信息显示调用GetByID时传入的是空字符串,说明testTeam1的ID字段未设置有效值。先确保testTeam1拥有合法的ID,比如:
var testTeam1 = &team.Team{ ID: "team-123", TeamOwnerID: "owner-456", // 其他必要字段 }
2. 补充GetByID方法的Mock
Update方法内部会先调用GetByID校验权限,因此必须在测试中Mock该方法的返回:
- 创建一个与
testTeam1拥有相同ID和TeamOwnerID的现有团队实例,用于GetByID的返回 - 先Mock GetByID的调用,再Mock Update的调用
修改后的测试用例示例:
t.Run("Update a team", func(t *testing.T) { teamRepo, _, ts := setupTeamService(teamIdGen, playerIdGen) // 构造现有团队,ID和TeamOwnerID与testTeam1一致 existingTeam := &team.Team{ ID: testTeam1.ID, TeamOwnerID: testTeam1.TeamOwnerID, } // 先Mock GetByID的调用,返回现有团队和nil错误 teamRepo.On("GetByID", testTeam1.ID).Return(existingTeam, nil) // 再Mock Update的调用 teamRepo.On("Update", testTeam1).Return(nil) result := ts.Update(testTeam1) assert.Nil(t, result) })
3. 确保MockRepo的GetByID方法正确实现
如果还存在问题,检查MockRepo的GetByID方法是否符合Testify的Mock规范,示例实现如下:
func (t *teamRepoMock) GetByID(id string) (*team.Team, AppError) { args := t.Called(id) // 注意返回值顺序:第一个是Team实例,第二个是AppError return args.Get(0).(*team.Team), args.Error(1) }
4. 错误场景的测试补充
对于"Update a team fails"的测试场景,同样需要Mock GetByID的调用,确保权限校验通过后,才会走到Update方法返回错误的逻辑:
t.Run("Update a team fails", func(t *testing.T) { teamRepo, _, ts := setupTeamService(teamIdGen, playerIdGen) existingTeam := &team.Team{ ID: testTeam1.ID, TeamOwnerID: testTeam1.TeamOwnerID, } teamRepo.On("GetByID", testTeam1.ID).Return(existingTeam, nil) expected := oopsErr teamRepo.On("Update", testTeam1).Return(expected) result := ts.Update(testTeam1) assert.EqualValues(t, expected.Error(), result.Error()) })
内容的提问来源于stack exchange,提问作者Waleem Ali
相关产品推荐
相关产品推荐

