Real examples of tests that make developers cry. Learn from these mistakes so you don't repeat them.
The Smell: Asserting internal calls/implementation details instead of observable behavior.
The Fix: Assert inputs/outputs and contract-level side effects; use fakes where helpful.
type UserStore interface {
Save(ctx context.Context, u User) error
}
// Service under test
type Service struct { store UserStore }
func (s Service) Register(ctx context.Context, email string) error {
u := User{Email: email, CreatedAt: time.Now()}
return s.store.Save(ctx, u)
}
// --- Test (bad) ---
type mockStore struct {
t *testing.T
calls int
lastSQL string
}
func (m *mockStore) Save(ctx context.Context, u User) error {
m.calls++
// Pretend we inspect a SQL string from deep in the impl
m.lastSQL = "INSERT INTO users(email, created_at) VALUES(?, ?)"
if !strings.Contains(m.lastSQL, "INSERT") {
m.t.Fatalf("expected INSERT")
}
if u.Email == "" {
m.t.Fatalf("email was empty")
}
return nil
}
func TestService_Register_Bad(t *testing.T) {
m := &mockStore{t: t}
s := Service{store: m}
if err := s.Register(context.Background(), "alice@example.com"); err != nil {
t.Fatalf("unexpected err: %v", err)
}
if m.calls != 1 {
t.Fatalf("expected Save to be called once, got %d", m.calls)
}
if !strings.Contains(m.lastSQL, "users") {
t.Fatalf("expected to touch users table")
}
}
type fakeStore struct {
saved []User
err error
}
func (f *fakeStore) Save(ctx context.Context, u User) error {
if f.err != nil { return f.err }
f.saved = append(f.saved, u)
return nil
}
func TestService_Register_Good(t *testing.T) {
fs := &fakeStore{}
s := Service{store: fs}
err := s.Register(context.Background(), "alice@example.com")
if err != nil { t.Fatalf("unexpected err: %v", err) }
if len(fs.saved) != 1 {
t.Fatalf("expected one user saved, got %d", len(fs.saved))
}
got := fs.saved[0]
if got.Email != "alice@example.com" {
t.Fatalf("email mismatch: got %q", got.Email)
}
if got.CreatedAt.IsZero() {
t.Fatalf("expected CreatedAt to be set")
}
}
func TestService_Register_PropagatesError(t *testing.T) {
fs := &fakeStore{err: errors.New("boom")}
s := Service{store: fs}
if err := s.Register(context.Background(), "bob@example.com"); err == nil {
t.Fatalf("expected error")
}
}