Updated 2025-05-31
gomock | testify + mockery | mockio | minimock | moq | |
---|---|---|---|---|---|
GitHub stars | |||||
Latest release date | |||||
Maintained | ✅ | ✅ | ✅ | ✅ | ✅ |
Notes | 1 | 2 | 3 | ||
Code generation 4 | ✅ | ✅ | ✅ 5 | ✅ | ✅ |
Works without code generation 6 | ❌ | ✅ | ✅ | ❌ | ❌ |
Use t.Cleanup() 7 |
✅ | ✅ | ✅ | ✅ | ❌ |
Support generics | ✅ | ✅ | ✅ | ✅ | ✅ |
Execute custom func 8 | ✅ | ✅ | ✅ | ✅ | ✅ |
Calls order 9 | ✅ | ✅ | ❌ | ❌ | ❌ |
Wait for time.Duration 10 |
❌ | ✅ | ❌ | ❌ | ❌ |
Wait for message from chan 11 |
❌ | ✅ | ❌ | ❌ | ❌ |
Panic 12 | ❌ | ✅ | ❌ | ❌ | ❌ |
Assert expectations with timeout | ❌ | ❌ | ❌ | ✅ | ❌ |
Return zero values by default 13 | ✅ | ❌ | ✅ | ❌ | ❌ |
Capturer 14 | ❌ | ✅ | ✅ | ✅ | ✅ |
Exact calls count 15 | ✅ | ✅ | ✅ | ✅ | ❌ |
Min/max calls count 16 | ✅ | ❌ | ❌ | ❌ | ❌ |
Called at least once | ✅ | ❌ | ✅ | ❌ | ❌ |
Don't check calls count | ✅ | ✅ | ✅ | ✅ | ❌ |
Expect once by default 17 | ✅ | ❌ | ❌ | ❌ | ❌ |
Any value | ✅ | ✅ | ✅ | ✅ | ❌ |
Equal to (reflect ) |
✅ | ✅ | ✅ | ✅ | ❌ |
Not equal to | ✅ | ❌ | ✅ | ❌ | ❌ |
Exact (== ) |
❌ | ❌ | ✅ | ❌ | ❌ |
One of values | ✅ | ❌ | ✅ | ❌ | ❌ |
Regex | ✅ | ❌ | ✅ | ❌ | ❌ |
Substring | ❌ | ❌ | ✅ | ❌ | ❌ |
Is nil |
✅ | ❌ | ✅ | ❌ | ❌ |
Not nil |
✅ | ❌ | ✅ | ❌ | ❌ |
Type is | ✅ | ✅ | ✅ | ❌ | ❌ |
Length is | ✅ | ❌ | ✔️ 18 | ❌ | ❌ |
Slice elements in any order | ✅ | ❌ | ✅ | ❌ | ❌ |
Slice contains | ❌ | ❌ | ✅ | ❌ | ❌ |
Map contains keys | ❌ | ❌ | ✅ | ❌ | ❌ |
Functional options | ❌ | ✅ | ❌ | ❌ | ❌ |
Logical operations on matchers | ✅ | ❌ | ❌ | ❌ | ❌ |
Custom matcher | ✅ | ✅ | ✅ | ✅ | ❌ |
func TestUberGomock(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)),
)
...
}
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()
...
}
func TestMockio(t *testing.T) {
ctrl := mock.NewMockController(t, mockopts.StrictVerify())
m := mock.Mock[MyInterface](ctrl)
mock.WhenDouble(m.Method(mock.AnyContext(), mock.Equal("abc"))).ThenReturn(123, nil).Verify(mock.Once())
mock.WhenDouble(m.AnotherMethod(mock.AnyContext(), mock.Regex("ab?c"))).Verify(mock.Once())
captor := mock.Captor[string]()
mock.WhenDouble(m.Method(mock.AnyContext(), captor.Capture()))
...
assert.Equal(t, "abc", captor.Last())
}
func TestMinimock(t *testing.T) {
ctrl := minimock.NewController(t)
m := NewMyInterfaceMock(ctrl)
m.MethodMock.When(minimock.AnyContext, "abc").Then(123, nil)
m.AnotherMethodMock.When(minimock.AnyContext, "abc").Then(0, nil)
...
}
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
-
Google stopped maintaining the original gomock with 9K stars, Uber forked it and continue development ↩
-
mockery/v3
, became a generic interface-based code generation framework, see blog post ↩ -
mockio
supports only amd64 and arm64 processors and it heavily depends on compiler internals and unsafe package, see docs ↩ -
CLI tool to auto generate mocks from interfaces ↩
-
While
mockio/v2
is designed to work without code generation, it also provides a template formockery/v3
, see docs ↩ -
Create mocks in runtime, without code generation ↩
-
Mock constructor uses
t.Cleanup()
to assert expectations after test by default ↩ -
Use arbitrary function to execute, allowing to implement any feature in the table ↩
-
Define expected order of calls ↩
-
Block execution of method using
time.Sleep()
↩ -
Block execution of method using
<- channel
↩ -
Panic instead of method execution ↩
-
Not defining return values leads to returning zero values ↩
-
Ability to capture actual call arguments to validate them later (not in mock) ↩
-
Define expected exact number of calls in test ↩
-
Define expected min/max number of calls in test ↩
-
Not defining number of calls leads to expectation that method to be called once ↩
-
There are only length matchers for slices and maps, not for strings ↩
@LandonTClipp, thanks for pointing me this. Most probably, the wording in the table needs to be better.
Typed expected arguments
means that a method to define expectation is typed. TheRunAndReturn
method doesn't define an expectation. In your example, the methodGet
does it, and it acceptsany
.But I've removed the wrong checkmark in Uber
gomock
for that feature.Actually, I realized that having
Typed expected arguments
means not having matches at all.UPD: The last statement is incorrect as mockio has matchers, and it's strictly typed at the same time.