Skip to content

Commit

Permalink
Fixed -mockNames not propagating to Recorder and ReturnCall types (#127)
Browse files Browse the repository at this point in the history
When you are trying to mock multiple interfaces with the same name and
similar methods (for example user.Service Create, post.Service Create,
etc..) there is collision in Recorder and ReturnCall types, the
-mockNames parameter only changes the main interface name, with the
changes proposed in this PR the correct mockName will be applied to the
Recorder and ReturnCall types.

Addresses #117
  • Loading branch information
UnAfraid committed Dec 19, 2023
1 parent 7bf3d91 commit 6dd8fe5
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 24 deletions.
2 changes: 1 addition & 1 deletion mockgen/internal/tests/exclude/interfaces.go
@@ -1,6 +1,6 @@
package exclude

//go:generate mockgen -source=interfaces.go -destination=mock.go -package=ignore -exclude_interfaces=IgnoreMe,IgnoreMe2
//go:generate mockgen -source=interfaces.go -destination=mock.go -package=exclude -exclude_interfaces=IgnoreMe,IgnoreMe2

type IgnoreMe interface {
A() bool
Expand Down
4 changes: 2 additions & 2 deletions mockgen/internal/tests/exclude/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions mockgen/internal/tests/mock_name/mocks.go
@@ -0,0 +1,4 @@
package mock_names

//go:generate mockgen -mock_names=Service=UserServiceMock -package mocks -typed -destination mocks/user_service.go -self_package go.uber.org/mock/mockgen/internal/tests/mock_name/mocks go.uber.org/mock/mockgen/internal/tests/mock_name/user Service
//go:generate mockgen -mock_names=Service=PostServiceMock -package mocks -typed -destination mocks/post_service.go -self_package go.uber.org/mock/mockgen/internal/tests/mock_name/mocks go.uber.org/mock/mockgen/internal/tests/mock_name/post Service
80 changes: 80 additions & 0 deletions mockgen/internal/tests/mock_name/mocks/post_service.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

79 changes: 79 additions & 0 deletions mockgen/internal/tests/mock_name/mocks/user_service.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions mockgen/internal/tests/mock_name/mocks_test.go
@@ -0,0 +1,44 @@
package mock_names

import (
"testing"

"go.uber.org/mock/gomock"
"go.uber.org/mock/mockgen/internal/tests/mock_name/mocks"
"go.uber.org/mock/mockgen/internal/tests/mock_name/post"
"go.uber.org/mock/mockgen/internal/tests/mock_name/user"
)

func TestMockNames(t *testing.T) {
ctrl := gomock.NewController(t)

userService := mocks.NewUserServiceMock(ctrl)
postService := mocks.NewPostServiceMock(ctrl)

gomock.InOrder(
userService.EXPECT().
Create("John Doe").
Return(&user.User{Name: "John Doe"}, nil),
postService.EXPECT().
Create(gomock.Eq("test title"), gomock.Eq("test body"), gomock.Eq(&user.User{Name: "John Doe"})).
Return(&post.Post{
Title: "test title",
Body: "test body",
Author: &user.User{
Name: "John Doe",
},
}, nil))
u, err := userService.Create("John Doe")
if err != nil {
t.Fatal("unexpected error")
}

p, err := postService.Create("test title", "test body", u)
if err != nil {
t.Fatal("unexpected error")
}

if p.Title != "test title" || p.Body != "test body" || p.Author.Name != u.Name {
t.Fatal("unexpected postService.Create result")
}
}
15 changes: 15 additions & 0 deletions mockgen/internal/tests/mock_name/post/service.go
@@ -0,0 +1,15 @@
package post

import (
"go.uber.org/mock/mockgen/internal/tests/mock_name/user"
)

type Post struct {
Title string
Body string
Author *user.User
}

type Service interface {
Create(title, body string, author *user.User) (*Post, error)
}
9 changes: 9 additions & 0 deletions mockgen/internal/tests/mock_name/user/service.go
@@ -0,0 +1,9 @@
package user

type User struct {
Name string
}

type Service interface {
Create(name string) (*User, error)
}
28 changes: 14 additions & 14 deletions mockgen/internal/tests/typed_inorder/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions mockgen/mockgen.go
Expand Up @@ -519,7 +519,7 @@ func (g *generator) GenerateMockMethods(mockType string, intf *model.Interface,
g.p("")
_ = g.GenerateMockMethod(mockType, m, pkgOverride, shortTp)
g.p("")
_ = g.GenerateMockRecorderMethod(intf, mockType, m, shortTp, typed)
_ = g.GenerateMockRecorderMethod(intf, m, shortTp, typed)
if typed {
g.p("")
_ = g.GenerateMockReturnCallMethod(intf, m, pkgOverride, longTp, shortTp)
Expand Down Expand Up @@ -607,7 +607,8 @@ func (g *generator) GenerateMockMethod(mockType string, m *model.Method, pkgOver
return nil
}

func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, mockType string, m *model.Method, shortTp string, typed bool) error {
func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, m *model.Method, shortTp string, typed bool) error {
mockType := g.mockName(intf.Name)
argNames := g.getArgNames(m, true)

var argString string
Expand All @@ -632,7 +633,7 @@ func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, mockType s

g.p("// %v indicates an expected call of %v.", m.Name, m.Name)
if typed {
g.p("func (%s *%vMockRecorder%v) %v(%v) *%s%sCall%s {", idRecv, mockType, shortTp, m.Name, argString, intf.Name, m.Name, shortTp)
g.p("func (%s *%vMockRecorder%v) %v(%v) *%s%sCall%s {", idRecv, mockType, shortTp, m.Name, argString, mockType, m.Name, shortTp)
} else {
g.p("func (%s *%vMockRecorder%v) %v(%v) *gomock.Call {", idRecv, mockType, shortTp, m.Name, argString)
}
Expand Down Expand Up @@ -661,7 +662,7 @@ func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, mockType s
}
if typed {
g.p(`call := %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, shortTp, m.Name, callArgs)
g.p(`return &%s%sCall%s{Call: call}`, intf.Name, m.Name, shortTp)
g.p(`return &%s%sCall%s{Call: call}`, mockType, m.Name, shortTp)
} else {
g.p(`return %s.mock.ctrl.RecordCallWithMethodType(%s.mock, "%s", reflect.TypeOf((*%s%s)(nil).%s)%s)`, idRecv, idRecv, m.Name, mockType, shortTp, m.Name, callArgs)
}
Expand All @@ -672,6 +673,7 @@ func (g *generator) GenerateMockRecorderMethod(intf *model.Interface, mockType s
}

func (g *generator) GenerateMockReturnCallMethod(intf *model.Interface, m *model.Method, pkgOverride, longTp, shortTp string) error {
mockType := g.mockName(intf.Name)
argNames := g.getArgNames(m, true /* in */)
retNames := g.getArgNames(m, false /* out */)
argTypes := g.getArgTypes(m, pkgOverride, true /* in */)
Expand All @@ -694,10 +696,10 @@ func (g *generator) GenerateMockReturnCallMethod(intf *model.Interface, m *model
ia := newIdentifierAllocator(argNames)
idRecv := ia.allocateIdentifier("c")

recvStructName := intf.Name + m.Name
recvStructName := mockType + m.Name

g.p("// %s%sCall wrap *gomock.Call", intf.Name, m.Name)
g.p("type %s%sCall%s struct{", intf.Name, m.Name, longTp)
g.p("// %s%sCall wrap *gomock.Call", mockType, m.Name)
g.p("type %s%sCall%s struct{", mockType, m.Name, longTp)
g.in()
g.p("*gomock.Call")
g.out()
Expand Down

0 comments on commit 6dd8fe5

Please sign in to comment.