Golang / GoLang Production Patterns and Web Standards Interview Questions
How do you write testable Go code using interfaces and mocks without a framework?
Go's implicit interface satisfaction means any struct with the right methods satisfies an interface — no registration or code generation required. This makes hand-written mocks straightforward, readable, and dependency-free.
// Interface in the consumer package (not the producer) type EmailService interface { Send(ctx context.Context, to, subject, body string) error } // Production implementation type SMTPEmailService struct { host string; port int } func (s *SMTPEmailService) Send(ctx context.Context, to, subject, body string) error { // ... real SMTP logic return nil } // Hand-written mock for tests type MockEmailService struct { Calls []string // track what was called ReturnErr error // control what error to return } func (m *MockEmailService) Send(ctx context.Context, to, subject, body string) error { m.Calls = append(m.Calls, to) return m.ReturnErr } // Functional mock â more flexible, inline in test type EmailServiceFunc func(ctx context.Context, to, subject, body string) error func (f EmailServiceFunc) Send(ctx context.Context, to, subject, body string) error { return f(ctx, to, subject, body) } // Test using the mock func TestWelcomeEmail(t *testing.T) { mock := &MockEmailService{} svc := NewUserService(nil, mock, slog.Default()) err := svc.Register(context.Background(), RegisterRequest{ Name: "Alice", Email: "alice@example.com", }) if err != nil { t.Fatal(err) } if len(mock.Calls) != 1 { t.Errorf("expected 1 email sent, got %d", len(mock.Calls)) } if mock.Calls[0] != "alice@example.com" { t.Errorf("email sent to wrong address: %s", mock.Calls[0]) } } // Test error path func TestWelcomeEmailFailure(t *testing.T) { mock := &MockEmailService{ReturnErr: errors.New("smtp down")} svc := NewUserService(nil, mock, slog.Default()) // Test that service handles email failure gracefully }
More Related questions...