moq icon indicating copy to clipboard operation
moq copied to clipboard

Generate mocks for interfaces with generic types

Open lucastorri opened this issue 3 years ago • 2 comments

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!

lucastorri avatar Apr 06 '22 21:04 lucastorri

Any update here?

fish-sammy avatar Sep 12 '22 13:09 fish-sammy

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

matryer avatar Oct 01 '22 08:10 matryer

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

sudo-suhas avatar Jun 21 '23 08:06 sudo-suhas

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
// 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 avatar Jun 21 '23 14:06 lucastorri

Thanks all for the support!

lucastorri avatar Jun 21 '23 14:06 lucastorri