matryer / moq

Interface mocking tool for go generate
http://bit.ly/meetmoq
MIT License
1.99k stars 126 forks source link

Generate mocks for interfaces with generic types #173

Closed lucastorri closed 1 year ago

lucastorri commented 2 years ago

Hi!

I went through the existing issues and was not sure whether one specific to supporting interfaces with generic types exists. I had a look at https://github.com/matryer/moq/issues/168, but this is about generating mocks for types which package uses generics.

In sum, I would like to have an interface such as:

//go:generate moq -stub -out publisher_mock.go . Publisher

type Publisher[M any] interface {
    Publish(ctx context.Context, msg M)
}

and be able to use a generic mock in my test:

publisher := PublisherMock[Something]{}

publisher.Publish(ctx, Something{})

Thank you!

fish-sammy commented 2 years ago

Any update here?

matryer commented 2 years ago

Moq hasn't been upgraded to support generics yet. We need to do it.

sudo-suhas commented 1 year ago

@lucastorri can you check if this is still an issue?

lucastorri commented 1 year ago

Hi @sudo-suhas, I can confirm that it works with the reported case.

In case anyone is interested, here is the generated code:

Generated code ```go // Code generated by moq; DO NOT EDIT. // github.com/matryer/moq package test import ( "context" "sync" ) // Ensure, that PublisherMock does implement Publisher. // If this is not the case, regenerate this file with moq. var _ Publisher[any] = &PublisherMock[any]{} // PublisherMock is a mock implementation of Publisher. // // func TestSomethingThatUsesPublisher(t *testing.T) { // // // make and configure a mocked Publisher // mockedPublisher := &PublisherMock{ // PublishFunc: func(ctx context.Context, msg M) { // panic("mock out the Publish method") // }, // } // // // use mockedPublisher in code that requires Publisher // // and then make assertions. // // } type PublisherMock[M any] struct { // PublishFunc mocks the Publish method. PublishFunc func(ctx context.Context, msg M) // calls tracks calls to the methods. calls struct { // Publish holds details about calls to the Publish method. Publish []struct { // Ctx is the ctx argument value. Ctx context.Context // Msg is the msg argument value. Msg M } } lockPublish sync.RWMutex } // Publish calls PublishFunc. func (mock *PublisherMock[M]) Publish(ctx context.Context, msg M) { callInfo := struct { Ctx context.Context Msg M }{ Ctx: ctx, Msg: msg, } mock.lockPublish.Lock() mock.calls.Publish = append(mock.calls.Publish, callInfo) mock.lockPublish.Unlock() if mock.PublishFunc == nil { return } mock.PublishFunc(ctx, msg) } // PublishCalls gets all the calls that were made to Publish. // Check the length with: // // len(mockedPublisher.PublishCalls()) func (mock *PublisherMock[M]) PublishCalls() []struct { Ctx context.Context Msg M } { var calls []struct { Ctx context.Context Msg M } mock.lockPublish.RLock() calls = mock.calls.Publish mock.lockPublish.RUnlock() return calls } ```
lucastorri commented 1 year ago

Thanks all for the support!