Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separated package for generated mock and proto codes #4

Open
AVM-Martin opened this issue May 2, 2023 · 2 comments
Open

Separated package for generated mock and proto codes #4

AVM-Martin opened this issue May 2, 2023 · 2 comments
Labels
enhancement New feature or request

Comments

@AVM-Martin
Copy link

AVM-Martin commented May 2, 2023

Is it possible to separate the package? We only need mock service when running unit test and won't generate it

Background

We need put generated mock inside gen/mock directory. The directory tree will look similar to the following

github.com/example/project
├── gen
│   ├── mock
│   │   └── example_grpc_mock.pb.go
│   ├── example.pb.go
│   └── example_grpc.pb.go
└── proto
    └── example.proto

and gen/mock/example_grpc_mock.pb.go file will import structs from github.com/example/project/gen

// Code generated by protoc-gen-go-grpc-mock. DO NOT EDIT.
// source: proto/example.proto

package mock_example

import (
	context "context"
	reflect "reflect"

	gomock "github.com/golang/mock/gomock"
	grpc "google.golang.org/grpc"

	contract "github.com/example/project/gen"
)

// ... omitted

// PostMethodV1 mocks base method.
func (m *MockExampleServiceClient) PostMethodV1(ctx context.Context, in *contract.PostMethodV1Request, opts ...grpc.CallOption) (*contract.PostMethodV1Response, error) {
	m.ctrl.T.Helper()
	varargs := []interface{}{ctx, in}
	for _, a := range opts {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "PostMethodV1", varargs...)
	ret0, _ := ret[0].(*contract.PostMethodV1)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ... omitted

// PostMethodV1 mocks base method.
func (m *MockExampleServiceServer) PostMethodV1(ctx context.Context, in *contract.PostMethodV1Request) (*contract.PostMethodV1Response, error) {
	m.ctrl.T.Helper()
	ret := m.ctrl.Call(m, "PostMethodV1", ctx, in)
	ret0, _ := ret[0].(*contract.PostMethodV1Response)
	ret1, _ := ret[1].(error)
	return ret0, ret1
}

// ... omitted

For further directory sample, you may see the official gomock example here

Further Discussion

If it is possible, we can refer the main generated golang code based on provided flag (i.e. proto_import_path)

@sorcererxw
Copy link
Owner

sorcererxw commented May 8, 2023

I understand your needs very well, but there are two problems:

  1. If the final file structure is like this:
github.com/example/project
├── gen
│   ├── mock
│   │   └── example_grpc_mock.pb.go
│   ├── example.pb.go
│   └── example_grpc.pb.go
└── proto
    └── example.proto

Then the example_grpc_mock.pb.go file should import the parent package:

// example_grpc_mock.pb.go
import (
   . "github.com/example/project/gen"
)

We tend to use . /;package_name in go_package to generate code to the relative path. However, with google.golang.org/protobuf/compiler/protogen alone, we cannot get the real import path of the parent package in code generation.
Of course, you could declare the full package path in the go_package, but this would be too demanding and not a good implementation.

  1. There is a small chance of causing a conflict, for example, if there is already a mock subdirectory:
github.com/example/project
├── proto
│   ├── mock
│   │   └── example2.proto
│   ├── example1.proto

For the reasons above, generating code to a subdirectory doesn't seem to be a common behavior of Go proto plugins. I haven’t found a good solution to above problems yet, so if you have a good idea, feel free to discuss.

@sorcererxw sorcererxw added the enhancement New feature or request label May 8, 2023
@AVM-Martin
Copy link
Author

AVM-Martin commented May 25, 2023

Hi, sorry for a late reply

  1. Yes, we could import the parent package that way, but I do not explicitly define the go_package (see this eliza.proto from bufbuild/connect-demo). I am using this convention because my protobuf contract will be imported from another repository and generated locally, so I need to define go_package on buf.gen.yaml (equivalent with --go_opt=M=$FILENAME=$IMPORT_PATH arg)

https://github.com/bufbuild/connect-demo/blob/4d0f5a60813773f228db9fadef566cf802715d31/buf.gen.yaml#L2-L5

managed:
  enabled: true
  go_package_prefix:
    default: github.com/bufbuild/connect-demo/internal/gen
  1. It doesn’t have to be under gen/mock directory, maybe under /mock directory on the repository root. This is my specific use case (and that means I won’t have proto/mock directory)

I'm open to contribute on this plugin, but I need some time to learn about the codebase

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants