mock icon indicating copy to clipboard operation
mock copied to clipboard

Add a helper method for inline setup of mocks

Open mniak opened this issue 1 year ago • 1 comments

Requested feature A helper method that would make inline construction of mocks possible.

Why the feature is needed

So the test code would look nicer

Proposed solution

Maybe something like a SETUP method in every mock, which woul receive a function that configures the mock.

Example (before):

ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockReader1 := NewMockDep1(ctrl)
mockReader1.EXPECT().
    ReadSomething(gomock.Any(), gomock.Any()).
    Return("first call", nil)
mockReader1.EXPECT().
    ReadSomething(gomock.Any(), gomock.Any()).
    Return("second call", nil)
mockReader1.EXPECT().
    ReadSomething(gomock.Any(), gomock.Any()).
    Return("third call", nil)

mockWriter := NewMockDep1(ctrl)
mockWriter.EXPECT().
    WriteSomething(gomock.Any(), gomock.Any()).
    Return("first call", nil)
mockWriter.EXPECT().
    WriteSomething(gomock.Any(), gomock.Any()).
    Return("second call", nil)
mockWriter.EXPECT().
    WriteSomething(gomock.Any(), gomock.Any()).
    Return("third call", nil)

sut := NewSystemUnderTest(mockReader, mockWriter)
sut.DoAction()

Example (after):


ctrl := gomock.NewController(t)
defer ctrl.Finish()

sut := NewSystemUnderTest(
    NewMockReader(ctrl).SETUP(func (mock *MockReader) {
        mock.EXPECT().
            ReadSomething(gomock.Any(), gomock.Any()).
            Return("first call", nil)
        mock.EXPECT().
            ReadSomething(gomock.Any(), gomock.Any()).
            Return("second call", nil)
        mock.EXPECT().
            ReadSomething(gomock.Any(), gomock.Any()).
            Return("third call", nil)
    }),
    NewMockWriter(ctrl).SETUP(func (mock *MockWriter) {
        mock.EXPECT().
            WriteSomething(gomock.Any(), gomock.Any()).
            Return("first call", nil)
        mock.EXPECT().
            WriteSomething(gomock.Any(), gomock.Any()).
            Return("second call", nil)
        mock.EXPECT().
            WriteSomething(gomock.Any(), gomock.Any()).
            Return("third call", nil)
    }),
)
sut.DoAction()

mniak avatar Dec 21 '23 18:12 mniak

I think I understand why this could reduce some hand-written function declarations if you wanted to re-use setup functions but it think that having multiple patterns for setting up mocks (one with a setup function and one without) would make mock code less uniform and make users uncertain about which approach to use (in most cases we want to reduce nesting).

From what I can tell the generated implementation would be a methods with a pointer receiver that takes in a variable with the same reference to the receiver when ideally there is one clear variable to modify.

If this is just for inline setup, would it be better to create external wrapper functions that you could call inline?

r-hang avatar Dec 26 '23 21:12 r-hang