Mockery is a popular mock generator for Go. I appreciate the effort behind it - the maintainers do great work. But starting with v3, the project seems to have taken a wrong turn.

Issue 1: A mock generator trying to be something bigger

Mockery v3 now requires a dedicated YAML configuration file:

with-expecter: true
packages:
  github.com/your/project/internal/service:
    interfaces:
      UserRepository:
      OrderService:
        config:
          with-expecter: false

//go:generate is no longer supported - you must use the config file. A mock generator shouldn’t need this. It should read interfaces and produce mocks. That’s it.

Issue 2: Hidden race conditions

Mockery uses testify/mock under the hood, which stores references to call arguments. Here’s what happens:

  1. When a mock is called, testify saves argument references in its internal Calls slice
  2. Arguments are stored until the test finishes
  3. At test cleanup, AssertExpectations accesses stored arguments again

With sync.Pool and parallel tests, this causes race conditions.

Service method that uses a pool:

var bufPool = sync.Pool{
    New: func() any { return new(bytes.Buffer) },
}

func (s *Service) Send(msg Message) error {
    buf := bufPool.Get().(*bytes.Buffer)
    defer bufPool.Put(buf)

    buf.Reset()
    buf.WriteString(msg.Body)

    return s.sender.Send(buf) // passing pooled buffer to dependency
}

Test with Mockery:

func TestSend(t *testing.T) {
    mockSender := NewMockSender(t)
    mockSender.EXPECT().
        Send(mock.Anything). // Mockery holds reference to buf
        Return(nil)

    svc := &Service{sender: mockSender}

    _ = svc.Send(Message{Body: "hello"})
    // buf returned to pool, but Mockery still references it
    // next test or goroutine reuses buf → race condition
}

Flaky tests that are hard to diagnose. The -race flag will catch it, but only if your test coverage triggers the race.

Alternative

Consider mockgen - simple, no configuration files, more idiomatic Go. It does one thing and does it well. And it doesn’t use testify, so it doesn’t have this specific issue.