Locally, docker compose will spin up N mysql instances and relevant services under test. Makefiles or bin scripts init things and run tests. Some teams have seed scripts or a snapshot of some sql state they want. When you run local integration tests, data is cleared/reset.<p>We use buildkite for CI/CD. It runs the same docker compose stuff as we do locally. It runs unit and acceptance tests. If green, it will auto deploy to our k8s staging cluster (though it worked similar when it deployed to vms). If staging is green, it can auto promote to a canary node in prod, and, depending on team set up, w ill auto roll out or allow manual gating for any additional QA. Version numbers are auto bumped by some internal tooling tied into the build system.<p>When we push to stage, the staging env has db instances but they are usually 1-2 nodes where in prod we will have more (3-30 nodes or more depending on the service). In staging, we run a suit of tests that exercise the end user experience. We also regularly run a slimmed down version of those tests in prod.<p>When it comes to unit tests, most of our teams do not mock the db. We use Go, and we will test by using test fakes - a struct that matches an interface is created in the test file and passed around. These tests validate error handling, log generation, sometimes metric generation, and, lastly, the happy path.<p>TL;DR - docker compose and scripts.