Introduction
Why an in-memory database validates code that production will reject.
Test against the real thing, not an imitation
Your test suite is green. Three hundred forty tests, eleven seconds, no failures. You deploy, and the first request in production fails with ERROR: column "created_at" is of type timestamp with time zone but expression is of type character varying. Nobody introduced a bug: the code you tested is exactly the code you deployed. What changed is the database. Your tests were talking to H2 in PostgreSQL compatibility mode, while production talks to PostgreSQL 16. H2 accepted the implicit conversion; PostgreSQL rejects it. Your suite didn't lie about your code, it lied about its environment.
This scenario is nothing exotic. H2 doesn't know jsonb, doesn't enforce the same string sorting rules depending on collation, accepts column names that PostgreSQL reserves, and handles transaction isolation levels with a flexibility that Oracle or SQL Server don't have. Each discrepancy is small. Together, they form an entire category of defects that your suite structurally cannot detect, and for which you get no signal before deployment. The problem isn't H2: it's believing that a test that passes against H2 tells you something about PostgreSQL.
Comments
Comments are powered by GitHub Discussions
Sign in with GitHub to join the discussion