Part of your problem here is that the code that creates the client, is the code that you are trying to test with a mock.
Using an interface you can pass a mock into a method / function that you are trying to test. Step 1. would be splitting the code that creates the client, from the code where you want to inject the mock.
You should define an interface that you are trying to mock, it will allow you to swap the actual / real implementation for a fake / mock version, something like:
type ImagesGetter interface {
func GetImages(ctx context.Context, in *pb.ImageListRequest) (*pb.ImageListResponse, error)
}
Then create a new struct type that will allow you to set the mock / real implementation.
type Lister struct {
images ImagesGetter
}
func (l *Lister) GetImagesList() {
// trimmed, but the grpc client should be defined
// and constructed outside this function and passed
// in in the images field of the Lister.
resp, err := l.images.GetImages(ctx, &pb.GetImagesRequest)
// trimmed ..
}
You can now construct the new Lister
model with a mock implementation:
type mock struct {}
func (m *mock) GetImages(ctx context.Context, in *pb.ImageListRequest) (*pb.ImageListResponse, error) {
// do mock implementation things here
}
And use it:
l := &Lister{images: &mock{}}