Unable to generate mocks in reflect mode
nezorflame opened this issue ยท 13 comments
Actual behavior A clear and concise description of what the bug is.
My project uses Go modules, but due to the CI restrictions we also make use of the vendor
folder.
So, our modules are synced by go mod tidy && go mod vendor
command.
While using mockgen
in a reflect
mode, I'm unable to generate mocks. Can't pinpoint exactly when this became broken as this was working fine before, but it doesn't anymore.
The error message:
โฏ go generate ./...
/Users/nezorflame/Go/src/github.com/nezorflame/mockgen-test - service - doc.go
prog.go:12:2: cannot find package "." in:
/Users/nezorflame/Go/src/github.com/nezorflame/mockgen-test/vendor/github.com/golang/mock/mockgen/model
prog.go:12:2: cannot find package "." in:
/Users/nezorflame/Go/src/github.com/nezorflame/mockgen-test/vendor/github.com/golang/mock/mockgen/model
prog.go:12:2: cannot find module providing package github.com/golang/mock/mockgen/model: working directory is not part of a module
prog.go:14:2: cannot find module providing package github.com/nezorflame/mockgen-test/internal/client: working directory is not part of a module
2020/10/22 19:41:04 Loading input failed: exit status 1
internal/service/doc.go:2: running "mockgen": exit status 1
Seems to be somewhat similar to the #423 but the proposed solution didn't work for me.
Expected behavior A clear and concise description of what you expected to
happen.
Mocks should've been generated fine.
To Reproduce Steps to reproduce the behavior
I've published a test project which can be used to reproduce the issue.
mockgen
is called during the go:generate
directive at internal/service/doc.go:
//go:generate echo $PWD - $GOPACKAGE - $GOFILE
//go:generate mockgen -package $GOPACKAGE -destination mocks_test.go github.com/nezorflame/mockgen-test/internal/client Producer
The interface to generate the mocks upon is pretty simple and is stored at internal/client/contract.go:
type Producer interface {
Produce(ctx context.Context, objects []string) error
}
So, the steps are:
- Download the project
- (Optional) Generate the mocks without the
vendor
:
a. Rungo mod tidy && go mod vendor
to clean up the dependencies
b. Rungo generate ./...
once - it'll work fine,mocks_test.go
file will be generated
c. Deletemocks_test.go
file to reproduce the error - Run
go generate ./...
- The error appears
It seems that the fact that vendor
contains dependencies somehow breaks the ability of mockgen
to generate the mocks, since the vendor-less mode works fine.
Additional Information
- gomock mode (reflect or source): reflect
- gomock version or git ref: v1.4.4
- golang version: v1.5.3
go env
output:
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/nezorflame/Library/Caches/go-build"
GOENV="/Users/nezorflame/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GOMODCACHE="<my_gopath>/pkg/mod"
GONOPROXY="my.company.com"
GONOSUMDB="my.company.com"
GOOS="darwin"
GOPATH="<my_gopath>"
GOPRIVATE="my.company.com"
GOPROXY="https://proxy.golang.org,https://goproxy.io,https://gocenter.io,direct"
GOROOT="<my_goroot>"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="<my_goroot>/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
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/4p/q8s4q9s50qbdl5vllqg5fs000000gp/T/go-build294373709=/tmp/go-build -gno-record-gcc-switches -fno-common"
The error message is due to github.com/golang/mock/mockgen/model
not being vendored golang/go#41936
I would assume the reason you started seeing it at an indeterminate time has to do with them slowly making modules the default behavior in new versions of golang.
How to fix this is a bit more tricky.
The golang program generated by reflection mode depends on github.com/golang/mock/mockgen/model
, but in most cases nothing else would depend on this, hence it not being included in the vendor folder.
There are probably some hacky work arounds like forcing the import with an _ "github.com/golang/mock/mockgen/model"
, but I'm not sure what the long term fix is.
cc @codyoss
As super hacky work around you can copy the directory github.com/golang/mock/mockgen/model
into your vendor folder
I think this is related to recent changes in Go tooling. Adding --build_flags=--mod=mod
is one workaround. The other would be to include an empty import of that package so it gets pulled in import _ "github.com/golang/mock/mockgen/model"
.
Thanks!
For now I'll use the proposed workaround with the empty import (and a comment to this issue), but it'd be nice to see this resolved.
Anything I could do to help further?
Thanks!
For now I'll use the proposed workaround with the empty import (and a comment to this issue), but it'd be nice to see this resolved.
Anything I could do to help further?
I think what needs to happen now is some discussion about how to conceptually solve this problem; any input would be welcome and appreciated.
The basic overview (IIUC @codyoss can correct me) is that during reflection mode we dynamically generate some golang source code for a new main program. This main program, the reflection program, is the heart of what makes reflection mode work.
The source code is written out by mockgen
and then mockgen
executes some shell commands to compile and run the reflection program.
Problem we are hitting is in the dependency management; the reflection program requires github.com/golang/mock/mockgen/model
but your code does not.
When the go
toolchain attempts to compile the reflection program it sees your vendor directory, but github.com/golang/mock/mockgen/model
is not contained and so it fails.
So we essentially have two different build environments that require different dependencies.
One of the problems is that the error message is so cryptic and unergonomic, it is impossible to figure out why this is happening. And the reason why (as comments above explain) is that that the mockgen/model
directory never was vendored in the first place.
My workaround (strangely enough) was to remove the whole vendor
directory, and this allows mockgen to work.
After looking more into this issue I am not sure there is too much we can do about this. For now I will treat this as a documentation issue and add some notes in the readme.
If documentation is the solution you could add a pointer to the readme in the error as this is a known problem and the error message printed is a dead end for the user.
Hi there, any chance this has changed since last year? I'm new to GoMock but ran into this. Thanks for all you do for Go and the OSS community in general!
Hey I also came across this issue today, Looks like installing the mockgen
in GOPATH
is not enough to make this work.
The ERROR I had
prog.go:12:2: missing go.sum entry for module providing package github.com/golang/mock/mockgen/model; to add:
go mod download github.com/golang/mock
prog.go:12:2: missing go.sum entry for module providing package github.com/golang/mock/mockgen/model; to add:
go mod download github.com/golang/mock
prog.go:14:2: no required module provides package github.com/escalopa/go-bank/db/sqlc: go.mod file not found in current directory or any parent directory; see 'go help modules'
prog.go:12:2: no required module provides package github.com/golang/mock/mockgen/model: go.mod file not found in current directory or any parent directory; see 'go help modules'
2022/11/27 00:08:24 Loading input failed: exit status 1
SOLUTION
Install the package using the following command
go get github.com/golang/mock/
The output should be like this
go: upgraded github.com/golang/mock v1.4.4 => v1.6.0
After so ran the mockgen command and everything worked. Notice Change command below to one that matches your project
mockgen -destination db/mock/store.go github.com/escalopa/go-bank/db/sqlc Store
As a result you should see the the following files have been updated
- go.mod
- go.sum
This is how to worked for me, Wish this might help ๐
Ran into this and resolve it by creating ./tools/tools.go
with the contents of:
package tools
import (
_ "github.com/golang/mock/mockgen/model"
)
Then I was able to:
go get github.com/golang/mock/mockgen/model
go mod vendor
go mod tidy
thnks it worked for me