uber-go / mock

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

Generating mocks (reflect mode) fails if interface contains methods with generic types #175

Closed yz89122 closed 1 month ago

yz89122 commented 7 months ago

Actual behavior A clear and concise description of what the bug is.

Same issue from github.com/golang/mock https://github.com/golang/mock/issues/677.

Interface:

package mypkg

type S struct{}

type GS[T any] struct {
    T T
}

type I interface {
    M() GS[*S]
}

Mock package:

package mypkgmock

//go:generate go run go.uber.org/mock/mockgen -destination=mock.go -package=$GOPACKAGE github.com/yz89122/gomock-test/mypkg I

Command:

go generate ./...
2024/04/24 06:33:24 Failed to format generated source code: mock.go:42:39: missing ',' in type argument list (and 1 more errors)
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/yz89122/gomock-test/mypkg (interfaces: I)
//
// Generated by this command:
//
//      mockgen -destination=mock.go -package=mypkgmock github.com/yz89122/gomock-test/mypkg I
//

// Package mypkgmock is a generated GoMock package.
package mypkgmock

import (
        mypkg "github.com/yz89122/gomock-test/mypkg"
        gomock "go.uber.org/mock/gomock"
        reflect "reflect"
)

// MockI is a mock of I interface.
type MockI struct {
        ctrl     *gomock.Controller
        recorder *MockIMockRecorder
}

// MockIMockRecorder is the mock recorder for MockI.
type MockIMockRecorder struct {
        mock *MockI
}

// NewMockI creates a new mock instance.
func NewMockI(ctrl *gomock.Controller) *MockI {
        mock := &MockI{ctrl: ctrl}
        mock.recorder = &MockIMockRecorder{mock}
        return mock
}

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

// M mocks base method.
func (m *MockI) M() mypkg.GS[*github.com/yz89122/gomock-test/mypkg.S] {
        m.ctrl.T.Helper()
        ret := m.ctrl.Call(m, "M")
        ret0, _ := ret[0].(mypkg.GS[*github.com/yz89122/gomock-test/mypkg.S])
        return ret0
}

// M indicates an expected call of M.
func (mr *MockIMockRecorder) M() *gomock.Call {
        mr.mock.ctrl.T.Helper()
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "M", reflect.TypeOf((*MockI)(nil).M))
}
exit status 1

Expected behavior A clear and concise description of what you expected to happen.

No error.

To Reproduce Steps to reproduce the behavior

  1. Run go generate ./... for above code.

Additional Information

Triage Notes for the Maintainers

thegodenage commented 6 months ago

Okay, I find it annoying and it blocks me. Can I take care of this one? 😄

tchung1118 commented 5 months ago

@cebilon123 You can submit a PR if you have a fix. We welcome any contribution.

arxeiss commented 3 months ago

Any progress? If I understand correctly, there is some issue with reflect package itself. But there should be new API in Go 1.22 based on this comment https://github.com/uber-go/mock/issues/197#issuecomment-2270138135

Can that help fix this issue too?