Skip to content

Instantly share code, notes, and snippets.

@halyph
Forked from maratori/golang-mocks.md
Created February 18, 2023 15:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save halyph/f5472c003a44445643813e5109aa456a to your computer and use it in GitHub Desktop.
Save halyph/f5472c003a44445643813e5109aa456a to your computer and use it in GitHub Desktop.
Comparison of golang mocking libraries

Comparison of golang mocking libraries

Updated 2022-12-22

gomock testify + mockery minimock moq

Library

GitHub stars s1 s2 + s3 s4 s5
Latest release date d1 d2 + d3 d4 d5
Maintained

Mock creation

Code generation 1
Not only code generation 2
Use t.Cleanup() 3
Support generics

DSL

Execute custom func 4
Typed expected arguments 5 ✖️ ✖️ ✔️ ✔️
Typed returned values 6 ✖️ ✔️ ✔️ ✔️
Calls order 7
Wait for time.Duration 8
Wait for message from chan 9
Panic 10
Assert expectations with timeout
Return zero values by default 11

Calls count

Exact calls count 12
Min/max calls count 13
Any positive calls count
Any calls count
Expect once by default 14

Matchers

Any value
Equal to
Not equal to
Is nil
Type is
Length is
Slice elements in any order
Custom matcher

Examples

gomock

func TestGomock(t *testing.T) {
	ctrl := gomock.NewController(t)
	m := NewMockMyInterface(ctrl)
	gomock.InOrder(
		m.EXPECT().Method(gomock.Any(), "abc").Return(123, nil),
		m.EXPECT().AnotherMethod(gomock.Any(), gomock.Len(3)),
	)
	...
}

testify/mock + mockery

func TestTestifyMock(t *testing.T) {
	m := mocks.NewMyInterface(t)
	m.EXPECT().Method(mock.Anything, "abc").After(5*time.Second).Return(123, nil).Once()
	m.EXPECT().AnotherMethod(mock.Anything, "abc").Return(0, nil).Once()
	...
}

minimock

func TestMinimock(t *testing.T) {
	ctrl := minimock.NewController(t)
	t.Cleanup(ctrl.Finish)
	m := NewMyInterfaceMock(ctrl)
	m.MethodMock.When(context.Background(), "abc").Then(123, nil)
	m.AnotherMethodMock.When(context.Background(), "abc").Then(0, nil)
	...
}

moq

func TestMoq(t *testing.T) {
	m := MyInterfaceMock{
		MethodFunc: func(ctx context.Context, s string) (int, error) {
			assert.Equal(t, "abc", s)
			return 123, nil
		},
		AnotherMethodFunc: func(ctx context.Context, s string) (int, error) {
			assert.Len(t, s, 1)
			return 0, nil
		},
	}
	t.Cleanup(func() {
		assert.Len(t, m.MethodCalls(), 1)
		assert.Len(t, m.AnotherMethodCalls(), 1)
	})
	...
}

Footnotes

  1. CLI tool to auto generate mocks from interfaces

  2. Allow writing mock manually, without code generation

  3. Mock constructor uses t.Cleanup() to assert expectations after test by default

  4. Use arbitrary function to execute, allowing to implement any feature in the table

  5. Defining expected arguments in test doesn't rely on empty interface{}

  6. Defining returned values in test doesn't rely on empty interface{}

  7. Define expected order of calls

  8. Block execution of method using time.Sleep()

  9. Block execution of method using <- channel

  10. Panic instead of method execution

  11. Not defining return values leads to returning zero values

  12. Define expected exact number of calls in test

  13. Define expected min/max number of calls in test

  14. Not defining number of calls leads to expectation that method to be called once

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment