golang / mock

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

mockgen: Source mode compiles package #275

Closed HeinOldewageRetro closed 4 years ago

HeinOldewageRetro commented 5 years ago

When using -source=interface.go the package that interface.go belongs to gets compiled/parsed before the mock is generated.

This is a problem if the tests that uses this mock also resides in the same package, as NewMockInterface won't exists.

This used to work on older versions.

balshetzer commented 5 years ago

Would it be possible for you to provide a small example that works with an older version and now doesn't?

Also, what is failing? Is it mockgen? Can you show us the command and its output?

On Wed, Mar 13, 2019, 8:00 AM HeinOldewageRetro notifications@github.com wrote:

When using -source=interface.go the package that interface.go belongs to gets compiled/parsed before the mock is generated.

This is a problem if the tests that uses this mock also resides in the same package, as NewMockInterface won't exists.

This used to work on older versions.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/golang/mock/issues/275, or mute the thread https://github.com/notifications/unsubscribe-auth/ABwtxmTKd4GNwH9NK5FsC6ZcnlsMIu7Kks5vWOhvgaJpZM4btDmt .

koenpunt commented 5 years ago

This is the same issue as what is being described in #274

HeinOldewageRetro commented 5 years ago

@koenpunt #274 is a problem with two interfaces and imports in the mock.

@balshetzer The error is from mock gen

/home/hein/gocode/src/github.com/HeinOldewageRetro/go_mock_test/tool/func_test.go:14:7: undeclared name: NewMockmyInterface
2019/03/14 14:28:42 Loading input failed: loading package failed
tool/interface.go:1: running "mockgen": exit status 1

It is run from go generate (but also fail when invoked on commandline)

//go:generate mockgen -source=interface.go -destination=iMock.go -package=tool

Small example at https://github.com/HeinOldewageRetro/go_mock_test

koenpunt commented 5 years ago

Ah you're right, the solution there was to use the -destination argument instead of output redirection.

ghostsquad commented 5 years ago

I'm already using -destination and still seeing the problem.

ghostsquad commented 5 years ago

nvm the reference above pointed me in the right direction, in that I need to use glide or dep to vendor the correct version of mock/mockgen then build/use the tool from the vendor directory.

var23rav commented 5 years ago

Before trying to generate mock, try to do go test . make sure, there is no error in source file.

HeinOldewageRetro commented 5 years ago

Before trying to generate mock, try to do go test . make sure, there is no error in source file.

The test wont compile without the mocks as it is what is referencing the mocks, in other words go test will always fail before mockgen was run.

ghostsquad commented 5 years ago

@HeinOldewageRetro correct, so you need to generate mocks before running tests.

horacimacias commented 5 years ago

what about re-generating mocks when the interface changed? what's the suggested way to do this?

In my case I generated mocks and created tests. Life was good. Then I modified my source and the interface changed. I want to re-generate the mocks so I can later update the tests to use the newly generated mocks. Problem is I cannot re-generate mocks with the tests not compiling; it would be good to have an option to bypass compiling the whole package.

balshetzer commented 5 years ago

I would put the interface being mocked in it's own, small, package. Either temporarily or permanently.

horacimacias commented 5 years ago

ok thanks

emman27 commented 5 years ago

Strongly agree for bypassing compiling for the sake of generating mocks, it's quite unnecessary and prevents us from keeping generated code out of source control. I don't see why generated code should be a part of a code repository, when we have go generate as a first class tool in Go.

This also breaks backwards compatibility from v1.2.0...

I'm in a situation where my tests rely on mockgen generated mocks, all within the same package.

victor-rt commented 5 years ago

add in func_test.go: // +build test with this line mockgen build binary without test file and successfully generate mock. it's workaround but may be appropriate. I had to roll back to 1.2.0 because 1.3.1 very slow build binaries for large amount of mocks.

codyoss commented 4 years ago

I second what @victor-rt said, a build tag is probably the best thing you can do as of right now. I will dig more into this eventually.

var23rav commented 4 years ago

Before trying to generate mock, try to do go test . make sure, there is no error in source file.

The test wont compile without the mocks as it is what is referencing the mocks, in other words go test will always fail before mockgen was run.

My point was different, Of course, to do the test we may need mock.

We need to ensure the existing code doesn't have any errors. For that you have to compile the code, can be anything go test or go run any command.

Consider you defined a package with an interface and there is some compilation error that exists in the code.

"If you feel so generous and try to execute mockgen on top of a package with error, it will fail." To be honest I did that, took some time to identify the code had some issue; Until I run the code using go test.

zagrev commented 4 years ago

Here is the issue in a nutshell.

  1. I mocked the interface, generated my unit tests using the mocks and everything works.
  2. I change the interface because that happens when I develop code. Now the mock code won't compile because the interfaces are wrong.
  3. I run mockgen to create new mock code with the right interface. Wrong! The mocks won't generate because the existing code doesn't compile.

How do I get out of this Catch-22? Can't create the mocks because the tests won't compile?

I added https://github.com/zagrev/go-mock-gen-failure with 3 tags to show the problem simply. The tags are: pre-change, post-change, post-remove

minicuts commented 4 years ago

@codyoss @zagrev @HeinOldewageRetro I think this bug is no longer in master. It was 'fixed' by #299 that was merged since version 1.3.1. Previously we used NeedCompiledGoFiles [0] but now that "Need value" is no longer used during package parsing. I just checked the reproducer provided by @zagrev with [1] and it works for me.

[0] https://godoc.org/golang.org/x/tools/go/packages#NeedCompiledGoFiles [1] go get github.com/golang/mock/mockgen@master

codyoss commented 4 years ago

Thanks for investigating, closing.