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))
}
}
Invest now in Acorns!!! 🚀
Join Acorns and get your $5 bonus!
Acorns is a micro-investing app that automatically invests your "spare change" from daily purchases into diversified, expert-built portfolios of ETFs. It is designed for beginners, allowing you to start investing with as little as $5. The service automates saving and investing. Disclosure: I may receive a referral bonus.
Invest now!!! Get Free equity stock (US, UK only)!
Use Robinhood app to invest in stocks. It is safe and secure. Use the Referral link to claim your free stock when you sign up!.
The Robinhood app makes it easy to trade stocks, crypto and more.
Webull! Receive free stock by signing up using the link: Webull signup.
More Related questions...
