Go使用sqlmock测试时模拟rows.Scan错误及mock预期不匹配排查
测试场景说明
我正在尝试为以下函数编写mock测试,目前在针对rows.Next()的返回逻辑设计测试用例时遇到了阻碍。
func (u *userRepository) GetList(idClient int) ([]UserPublic, rest_errors.RestErr) { stmt, err := u.client.Prepare(queryGetUserList) if err != nil { logger.Error("Error when trying to prepare get user list statement", err) return nil, rest_errors.NewInternalServerError("Error when tying to get user list", errors.New("database error")) } defer stmt.Close() var userList []UserPublic var user UserPublic rows, errStmt := stmt.Query(idClient) if errStmt != nil { logger.Error("Error when trying to query the user list", errStmt) return nil, rest_errors.NewInternalServerError("Error when tying to get the user list", errors.New("database error")) } for rows.Next() { if getErr := rows.Scan(&user.Id, &user.Name, &user.FirstSurname, &user.SecondSurname, &user.Email, &user.BirthDate, &user.identityNumberSql, &user.clinicalNumberSql, &user.cardSql, &user.phoneNumberSql, &user.Role, &user.DateCreated); getErr != nil { logger.Error("Error when trying to get user list", getErr) return nil, mysql_utils.ParseError(getErr) } userList = append(userList, user) } return userList, nil }
当前编写的测试用例
func TestUserGetListErrorScanRows (t *testing.T) { db, mock, err = getMockDB(t) defer db.Close() s := NewUserDaoMySQL(db) t.Run("Error scanning rows", func(t *testing.T) { rows := sqlmock.NewRows([]string{"id", "name", "first_surname", "second_surname", "email", "birth_date", "identity_number", "clinical_number", "card", "phone_number", "role", "date_created"}).AddRow(0, user.Name, user.FirstSurname, user.SecondSurname, user.Email, user.BirthDate, user.IdentityNumber, user.ClinicalNumber, user.Card, user.PhoneNumber, user.Role, user.DateCreated). RowError(1, fmt.Errorf("row error")) mock.ExpectPrepare("SELECT (.+) FROM user").ExpectQuery().WillReturnRows(rows) rs, errDb := db.Query("SELECT (.+) FROM user") fmt.Println(errDb) defer rs.Close() for rs.Next() { u := UserPublic{ Id: 0, Name: "", FirstSurname: "", SecondSurname: "", Email: "", BirthDate: "", IdentityNumber: "", ClinicalNumber: "", IdInsuranceCompany: 0, Card: "", IdClient: 0, PhoneNumber: "", Role: 0, DateCreated: "", } err := rs.Scan(&u.Id, &u.Name, &u.FirstSurname, &u.SecondSurname, &u.Email, &u.BirthDate, &u.IdentityNumber, &u.ClinicalNumber, &u.Card, &u.PhoneNumber, &u.Role, &u.DateCreated) if err != nil { fmt.Println("got scan error:", err) break } } id, err := s.GetList(int(user.IdClient)) assert.NotNil(t, err) assert.Nil(t, id) }) }
运行时报错信息
使用空参数调用SELECT (.+) FROM user的Query方法未被预期,下一个执行预期为ExpectedPrepare => 要求先执行匹配对应SQL的Prepare语句:
- 匹配SQL规则:
SELECT (.+) FROM user
待解决问题
- 分析上述报错的产生原因
- 掌握正确使用sqlmock模拟
rows.Scan返回错误的方法,完成对应异常分支的测试
内容的提问来源于stack exchange,提问作者Antoni
相关产品推荐
相关产品推荐

