golang / mock

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

Gomock generates bad files when used on generated protobuf golang files #207

Closed veqryn closed 5 years ago

veqryn commented 6 years ago

I am using the latest mockgen as of today.

When I use mockgen against generated protobuf golang files, the resulting generated mock file is unusable.

These are the errors I get:

# github.com/ReturnPath/ecm/examples/proto/mock_proto
examples\proto\mock_proto\mock_proto.go:39:65: undefined: HelloReq

It appears that mockgen is not namespacing input fields.

Here is the command I am running: mockgen --destination=./examples/proto/mock_proto/mock_proto.go --source=./examples/proto/hello.pb.go

Here is the proto file I am running it against:

syntax = "proto3";

package examples;
option go_package = "proto";

import "google/api/annotations.proto";

service Hello {
  rpc EnglishHello (HelloReq) returns (HelloResp) {
        option (google.api.http) = {
            get: "/hello"
        };
    }
}

message HelloReq {}

message HelloResp {
    string message = 1;
}

Against this I run the following command to generate golang protobuf stuff: protoc -I=./include -I=./vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis -I=./examples/proto/ ./examples/proto/hello.proto --go_out=plugins=grpc:./examples/proto/ --grpc-gateway_out=logtostderr=true:./examples/proto --swagger_out=logtostderr=true:./examples/proto

Here is a snippet from the resulting file:

//...

type HelloClient interface {
    EnglishHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error)
}

type helloClient struct {
    cc *grpc.ClientConn
}

func NewHelloClient(cc *grpc.ClientConn) HelloClient {
    return &helloClient{cc}
}

func (c *helloClient) EnglishHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
    out := new(HelloResp)
    err := c.cc.Invoke(ctx, "/examples.Hello/EnglishHello", in, out, opts...)
    if err != nil {
        return nil, err
    }
    return out, nil
}

//...

And then I run the above mockgen against that, and I this snippet:

//...

func NewMockHelloClient(ctrl *gomock.Controller) *MockHelloClient {
    mock := &MockHelloClient{ctrl: ctrl}
    mock.recorder = &MockHelloClientMockRecorder{mock}
    return mock
}

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

// EnglishHello mocks base method
func (m *MockHelloClient) EnglishHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
    varargs := []interface{}{ctx, in}
    for _, a := range opts {
        varargs = append(varargs, a)
    }
    ret := m.ctrl.Call(m, "EnglishHello", varargs...)
    ret0, _ := ret[0].(*HelloResp)
    ret1, _ := ret[1].(error)
    return ret0, ret1
}

//...

You can see the problem right here: func (m *MockHelloClient) EnglishHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {

It should be: func (m *MockHelloClient) EnglishHello(ctx context.Context, in *proto.HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {

HelloReq needs an import and needs to be namespaced.

I don't know why this is happening for all my proto files, but doesn't happen for anything else I use mockgen against.

codyoss commented 5 years ago

Hey @veqryn do you know if this is still an issue for you? It looks like some work was done that might have solved this.

codyoss commented 5 years ago

I ran the above code and the generated mock is now func (m *MockHelloClient) EnglishHello(arg0 context.Context, arg1 *proto.HelloReq, arg2 ...grpc.CallOption) (*proto.HelloResp, error). Closing as this appears fixed.