petergtz / pegomock

Pegomock is a powerful, yet simple mocking framework for the Go programming language
Apache License 2.0
254 stars 28 forks source link

pegomock generate panics with init function containing Println #97

Closed chidiwilliams closed 4 years ago

chidiwilliams commented 4 years ago

x.go

package x

import "fmt"

func init() {
    fmt.Println("")
}

type Foo interface {
    Bar() error
}

Running pegomock generate [package-path] Foo generates the following error:

panic: Loading input failed: gob: unknown type id or corrupted data

goroutine 1 [running]:
github.com/petergtz/pegomock/pegomock/filehandling.GenerateMockSourceCode(0xc0000aab20, 0x2, 0x2, 0x0, 0x0, 0xc000098370, 0x6, 0x0, 0x0, 0x0, ...)
        /Users/chidiwilliams/go/src/github.com/petergtz/pegomock/pegomock/filehandling/filehandling.go:110 +0x5b7
github.com/petergtz/pegomock/pegomock/filehandling.GenerateMockFile(0xc0000aab20, 0x2, 0x2, 0xc000134050, 0x45, 0x0, 0x0, 0xc000098370, 0x6, 0x0, ...)
        /Users/chidiwilliams/go/src/github.com/petergtz/pegomock/pegomock/filehandling/filehandling.go:64 +0xdd
github.com/petergtz/pegomock/pegomock/filehandling.GenerateMockFileInOutputDir(0xc0000aab20, 0x2, 0x2, 0xc000022084, 0x34, 0x0, 0x0, 0x0, 0x0, 0xc000098370, ...)
        /Users/chidiwilliams/go/src/github.com/petergtz/pegomock/pegomock/filehandling/filehandling.go:40 +0x17f
main.Run(0xc0000a6000, 0x4, 0x4, 0x143e240, 0xc000090008, 0x143e220, 0xc000010010, 0xc000130000, 0xc00007a060)
        /Users/chidiwilliams/go/src/github.com/petergtz/pegomock/pegomock/main.go:116 +0x22e3
main.main()
        /Users/chidiwilliams/go/src/github.com/petergtz/pegomock/pegomock/main.go:37 +0xa8

However, the mock is generated if I:

petergtz commented 4 years ago

Hi @chidiwilliams,

Thanks for reporting this. This is in indeed a problem in Pegomock. The reason why it is working when you specify the filepath instead, is that Pegomock uses a completely different mechanism to discover the interface methods when you specify a file instead of a package.

Here's what you can do, if you want to make it work with packages too. Instead of

pegomock generate [package-path] Foo

use

pegomock generate --use-experimental-model-gen [package-path] Foo

If you're interested in the internals, here's what's happening:

Without the --use-experimental-model-gen, pegomock will generate a program that imports your package and then use Go's introspection features to learn about its interfaces. It will then print out the interfaces+methods to StdOut, where it is picked up by Pegomock and used to generate the mock code. Now with your Println in the Init function, that messes up the output on StdOut.

With the --use-experimental-model-gen, pegomock will use a proper Go code parser to understand the interfaces in your code. It never runs any code and therefore also no Init methods.

The plan is to eventually make --use-experimental-model-gen the default.

I'd be curious to hear if that flag works for you.

Thank you, Peter

chidiwilliams commented 4 years ago

Thanks, @petergtz! It works perfectly as you said.