golang / mock

GoMock is a mocking framework for the Go programming language.
Apache License 2.0
9.32k stars 607 forks source link

cannot set destination package name same with source package name #323

Closed SeananXu closed 5 years ago

SeananXu commented 5 years ago

Could you please help me solve this problem, thank you very much

What happened: the destination file import current package with alias name when destination package same as source

What you expected to happen: the destination file should use the same package content directly

How to reproduce it (as minimally and precisely as possible):

  1. create project mockgen(outside gopath)
  2. init go mod
  3. create api directory
  4. create api.go
    
    package api

type Api interface { Test() Test }

type Test struct { }

5. open terminal and run `mockgen -source=api.go -destination=mock.go -package=api`

$mockgen -source=api.go -destination=mock.go -package=api // Code generated by MockGen. DO NOT EDIT. // Source: api.go

// Package api is a generated GoMock package. package api

import ( api "gendemo/api" gomock "github.com/golang/mock/gomock" reflect "reflect" )

// MockApi is a mock of Api interface type MockApi struct { ctrl gomock.Controller recorder MockApiMockRecorder }

// MockApiMockRecorder is the mock recorder for MockApi type MockApiMockRecorder struct { mock *MockApi }

// NewMockApi creates a new mock instance func NewMockApi(ctrl gomock.Controller) MockApi { mock := &MockApi{ctrl: ctrl} mock.recorder = &MockApiMockRecorder{mock} return mock }

// EXPECT returns an object that allows the caller to indicate expected use func (m MockApi) EXPECT() MockApiMockRecorder { return m.recorder }

// Test mocks base method func (m *MockApi) Test() api.Test { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Test") ret0, _ := ret[0].(api.Test) return ret0 }

// Test indicates an expected call of Test func (mr MockApiMockRecorder) Test() gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Test", reflect.TypeOf((*MockApi)(nil).Test)) }

6 run `go build` 

$go build can't load package: import cycle not allowed package gendemo/api imports gendemo/api



**demo project**: 
https://github.com/SeananXu/gendemo

**configuration**:
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/seanan/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/seanan/go"
GOPROXY="http://goproxy.io"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/l6/f61jwkp9535749glynyqb2pc0000gn/T/go-build279678536=/tmp/go-build -gno-record-gcc-switches -fno-common"

Darwin bilibilideMacBook-Pro.local 18.7.0 Darwin Kernel Version 18.7.0: Thu Jun 20 18:42:21 PDT 2019; root:xnu-4903.270.47~4/RELEASE_X86_64 x86_64
tscott0 commented 5 years ago

From what I understand, the fix would involve generating the same mock but without the offending import. Pseudocode:

if destination_package == source_package {
   // don't add import line
}

Keeping mocks in a different package has a few advantages, perhaps explaining why this hasn't come up before.

Can you give a bit more information around your use-case?

tscott0 commented 5 years ago

The self_package flag to mockgen will also do what you need, I believe.

https://github.com/golang/mock/blob/master/mockgen/mockgen.go#L51

SeananXu commented 5 years ago

From what I understand, the fix would involve generating the same mock but without the offending import. Pseudocode:

if destination_package == source_package {
   // don't add import line
}

Keeping mocks in a different package has a few advantages, perhaps explaining why this hasn't come up before.

  • Logical separation of mocks and implementation. I wouldn't expect to see mocks, used primarily for testing, in the same package as the thing they mock. If you imported api in a different context, you would also be importing the mock. It should be a test dependency only.
  • Less confusion. Assuming you opted to generate the mock in a different directory but gave the same package name, the package api could still be confusing. The default package name of mock_api is much clearer when importing and using the mock.

Can you give a bit more information around your use-case?

I will follow your advice, it makes sense to me, thanks!

SeananXu commented 5 years ago

The self_package flag to mockgen will also do what you need, I believe.

https://github.com/golang/mock/blob/master/mockgen/mockgen.go#L51

I solved my problem by using self_package flag, but I will use mock_api instead of api. It is more appropriate to me, thanks!