Golang / GoLang System Architecture and Testing Interview Questions
Explain the difference between mocks, stubs, and fakes in Go testing. When do you use each?
These three terms are often used interchangeably, but they describe different test double patterns with different purposes. Go's implicit interfaces make all three easy to implement without a framework.
| Type | Purpose | Returns | Verifies calls? |
|---|---|---|---|
| Stub | Returns pre-programmed responses to specific calls | Fixed values | No |
| Fake | Working implementation with simplified logic (e.g., in-memory DB) | Realistic values | No |
| Mock | Records calls and verifies expected interactions | Pre-programmed OR real | Yes — asserts call count, order, args |
// Interface to test against type UserRepository interface { FindByID(ctx context.Context, id int) (*User, error) Save(ctx context.Context, user *User) error } // STUB: returns fixed values, no logic type stubUserRepo struct { user *User err error } func (s *stubUserRepo) FindByID(_ context.Context, _ int) (*User, error) { return s.user, s.err } func (s *stubUserRepo) Save(_ context.Context, _ *User) error { return nil } // FAKE: in-memory map â works like a real repo but without a DB type fakeUserRepo struct { mu sync.Mutex users map[int]*User nextID int } func (f *fakeUserRepo) FindByID(_ context.Context, id int) (*User, error) { f.mu.Lock(); defer f.mu.Unlock() u, ok := f.users[id] if !ok { return nil, ErrNotFound } return u, nil } func (f *fakeUserRepo) Save(_ context.Context, u *User) error { f.mu.Lock(); defer f.mu.Unlock() f.nextID++; u.ID = f.nextID f.users[u.ID] = u return nil } // MOCK: records calls for assertion type mockUserRepo struct { FindByIDCalls []int SaveCalls []*User stub stubUserRepo } func (m *mockUserRepo) FindByID(ctx context.Context, id int) (*User, error) { m.FindByIDCalls = append(m.FindByIDCalls, id) return m.stub.FindByID(ctx, id) } func (m *mockUserRepo) Save(ctx context.Context, u *User) error { m.SaveCalls = append(m.SaveCalls, u) return m.stub.Save(ctx, u) } // Test using mock func TestService_Register(t *testing.T) { mock := &mockUserRepo{stub: stubUserRepo{}} svc := NewUserService(mock) svc.Register(context.Background(), "alice@example.com") if len(mock.SaveCalls) != 1 { t.Errorf("expected 1 Save call, got %d", len(mock.SaveCalls)) } }
More Related questions...