在调用mockgen的Return Method期间,预期值发生了变化。

huangapple go评论79阅读模式
英文:

Expected value is changed in Return Method of mockgen during its call

问题

我是你的中文翻译助手,以下是翻译好的内容:

我刚开始学习Go语言,最近尝试使用gomock包编写测试用例。我遇到了一个奇怪的问题。我正在尝试为GetUsers编写测试用例,其实现如下:

func (ctrl *HttpController) GetUsers(w http.ResponseWriter, r *http.Request) {

	users := ctrl.DS.GetUsers()
	
    // 修改了用户的名称
	users[0].Name = "User C"
	utility.JsonOkResponse(w, users)
} 

这是我的测试函数:

func TestGetUsers_Success(t *testing.T) {

	// 设置模拟接口
	ctrl, ds, _ := setup(t)

	// 设置预期的函数调用
	expected := mock_data.Users
	ds.EXPECT().GetUsers().Return(expected)

	// 创建请求
	req := httptest.NewRequest("GET", "/users", nil)

	// 生成路由器
	mux := mux.NewRouter()
	mux.HandleFunc("/users", ctrl.GetUsers)

	// 创建响应记录器
	resp := httptest.NewRecorder()
	mux.ServeHTTP(resp, req)

	// 检查响应内容
	assert.Equal(t, http.StatusOK, resp.Code)

	var users []model.User
	json.Unmarshal(resp.Body.Bytes(), &users)

	assert.Equal(t, expected, users)
}

这是mock_data.Users的定义:

var Users = []model.User{user1, user2}

// 示例用户数据
var user1 = model.User{
	ID:       1,
	Name:     "User A",
	Email:    "usera@gmail.com",
}

var user2 = model.User{
	ID:       2,
	Name:     "User B",
	Email:    "userb@gmail.com",
}

现在,我正在尝试不同的场景以便更好地理解。所以,在这种情况下,我的测试用例应该失败(尽管它仍然通过),因为我在GetUsers函数中更改了一个用户的名称,但奇怪的是,测试用例仍然通过,并且当我执行assert.Equal(t, expected, users)时,expected中的值也被更改为新的用户名User C。是不是在mockgen的Return方法中将expected值作为指针传递,还是我漏掉了一些基本的东西?

英文:

I am new to Go and recently, I am trying to write test cases using gomock package. I encountered a strange problem. I am trying to write test case for GetUsers whose
implementation is

func (ctrl *HttpController) GetUsers(w http.ResponseWriter, r *http.Request) {

	users := ctrl.DS.GetUsers()
	
    // changed the name of the user
	users[0].Name = "User C"
	utility.JsonOkResponse(w, users)
} 

This is my test function

func TestGetUsers_Success(t *testing.T) {

	// setup mock interfaces
	ctrl, ds, _ := setup(t)

	// setup expected function calls
	expected := mock_data.Users
	ds.EXPECT().GetUsers().Return(expected)

	// create the request
	req := httptest.NewRequest("GET", "/users", nil)

	// generate router
	mux := mux.NewRouter()
	mux.HandleFunc("/users", ctrl.GetUsers)

	// create response recorder
	resp := httptest.NewRecorder()
	mux.ServeHTTP(resp, req)

	// check response contents
	assert.Equal(t, http.StatusOK, resp.Code)

	var users []model.User
	json.Unmarshal(resp.Body.Bytes(), &users)

	assert.Equal(t, expected, users)
}

These are the mock_data.Users

var Users = []model.User{user1, user2}

// sample user data
var user1 = model.User{
	ID:       1,
	Name:     "User A",
	Email:    "usera@gmail.com",
}

var user2 = model.User{
	ID:       2,
	Name:     "User B",
	Email:    "userb@gmail.com",
}

Now, I was expermenting with different scenarios for better understanding. So, in this case my test case should fail (although it still passes) because I changed one of the user's name in GetUsers function but strangely, the test case still passes and when I do assert.Equal(t, expected, users) the value in the expected is also changed with new user name User C. Is the expected value passed as pointer in Return method of mockgen or Am I missing something basic ?

答案1

得分: 1

这是因为当你执行expected := mock_data.Users时,你只是复制了切片头部,而没有复制底层数组,所以对第一个切片数组的更改会影响到另一个切片。请参考这篇文章获取更多详细信息。

如果你想复制切片,你需要使用内置的copy函数,像这样:

expected := make([]model.User, len(mock_data.Users))
copy(expected, mock_data.Users)
英文:

This happens because when you do expected := mock_data.Users you are making a copy of the slice header, but not the underlying array, so changes to the array of the first slice will change the other. Please take a look at this article for more details.

If you want to make a copy of the slice you need to use the builtin copy function, like so:

expected := make([]model.User, len(mock_data.Users))
copy(expected, mock_data.Users)

huangapple
  • 本文由 发表于 2021年11月14日 21:42:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/69963580.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定