Home >Backend Development >Golang >Assertion: Mock: I don't know what to return because the method call was unexpected Error while writing unit test in Go
In this article, php editor Xiaoxin will introduce you to a common error that occurs when writing unit tests in the Go language, that is, assertion errors. When we write unit tests, we sometimes encounter situations where the return value cannot be determined, which can lead to unexpected method call errors. In this article, we will discuss the causes and solutions to this problem to help you better handle assertion errors and ensure the accuracy and reliability of your unit tests.
I use testify
in go to write unit tests for my service methods. All methods work fine except the update method, because during the update In the method, I call another method of the same service ("getbyid") in the update method.
Implement the update method in my service:
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) }
mockrepo update method:
func (t *teamrepomock) update(team *team.team) apperror { args := t.called(team) if args.error(0) != nil { return newnotfounderror(args.error(0)) } return nil }
Test implementation:
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()) }) }
Now when I run the test I get the following 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:
I tried calling .on("update")
before and after calling mock.on("getbyid")
in the test function implementation but it doesn't work and I also modified the mockrepo update function but it didn't work.
Let me try to help you solve your problem. I copied the repository with some simplifications just to post the relevant code. If I'm not wrong in your solution, there is a service (teamservice
) that calls some methods provided by the underlying package (teamrepo
). You want to test the update
method of the teamservice
structure. After reviewing, let me show the code first and then I will try to explain each file:
repo/repo.go
package repo type team struct { id int teamownerid int name string } type teamrepo struct{} func (t *teamrepo) getbyid(id int) (team, error) { return team{id: id, teamownerid: id, name: "myteam"}, nil } func (t *teamrepo) update(team team) error { return nil }
In this file we can find the method to simulate. The methods are: getbyid
and update
. Obviously this isn't your actual code, but that doesn't matter right now.
services/service.go
package services import ( "errors" "testifymock/repo" ) type teamservice struct { tr teamrepointerface } func newteamservice(repo teamrepointerface) *teamservice { return &teamservice{ tr: repo, } } type teamrepointerface interface { getbyid(id int) (repo.team, error) update(team repo.team) error } func (ts *teamservice) update(team *repo.team) error { t, err := ts.tr.getbyid(team.id) if err != nil { return err } if t.teamownerid != team.teamownerid { return errors.new("forbidden") } return ts.tr.update(*team) }
Here we can see in the test code the service that will become our system under test (sut
). With dependency injection, we will take advantage of the functionality provided by the repo
package injected through the interface teamrepointerface
.
services/service_test.go
package services import ( "errors" "testing" "testifymock/repo" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) // 1. declare the mock struct type teamRepoMock struct { mock.Mock } // 2. implement the interface func (m *teamRepoMock) GetByID(id int) (repo.Team, error) { args := m.Called(id) return args.Get(0).(repo.Team), args.Error(1) } func (m *teamRepoMock) Update(team repo.Team) error { args := m.Called(team) return args.Error(0) } func TestUpdate(t *testing.T) { t.Run("GoodUpdate", func(t *testing.T) { // 3. instantiate/setup mock repoMock := new(teamRepoMock) repoMock.On("GetByID", 1).Return(repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}, nil).Times(1) repoMock.On("Update", repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}).Return(nil).Times(1) sut := NewTeamService(repoMock) err := sut.Update(&repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}) // 4. check that all expectations were met on the mock assert.Nil(t, err) assert.True(t, repoMock.AssertExpectations(t)) }) t.Run("BadUpdate", func(t *testing.T) { // 3. instantiate/setup mock repoMock := new(teamRepoMock) repoMock.On("GetByID", 1).Return(repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}, nil).Times(1) repoMock.On("Update", repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}).Return(errors.New("some error while updating")).Times(1) sut := NewTeamService(repoMock) err := sut.Update(&repo.Team{ID: 1, TeamOwnerID: 1, Name: "test"}) // 4. check that all expectations were met on the mock assert.Equal(t, "some error while updating", err.Error()) assert.True(t, repoMock.AssertExpectations(t)) }) }
In the code you can find some comments to better detail what is happening. As you can guess, the problem is that this call is missing in the code:
repomock.on("getbyid", 1).return(repo.team{id: 1, teamownerid: 1, name: "test"}, nil).times(1)
If you run my solution it should work for you too.
If this solves your problem or you have any other questions, please let me know!
The above is the detailed content of Assertion: Mock: I don't know what to return because the method call was unexpected Error while writing unit test in Go. For more information, please follow other related articles on the PHP Chinese website!