DB connections themselves belong to another class (say, DbConn), which is not a singleton, and does not keep global state. But user code never instantiates that directly, and only ever calls DB::get(), which does know about global state, and figures out whether an existing connection should be reused.
If you need to set up things in a unit test so that DB::get() will return some kind of mock object, then you call some kind of DB::setupMock() method first.
Basically, I'm taking the kind of code that would go into the DB section of a DI configuration, and putting it in a separate class of its own, which is fully in charge of that particular bit of functionality: providing DB connections to the application.
And since it's functionally a global, I'm embracing that and making its method(s) and state static. Application startup calls DB::init() once, and then it's ready to go.