Much unit testing seems to paradoxically exist to justify OOP than to really test functionality. You'll never need to swap databases (and your DB abstraction layer probably wouldn't isolate all those problems anyway), but hey it lets you substitute mocks that let you verify that your implementation of the mock operates according to the code you happen to have written. So let's add that extra layer of abstraction, break all our "go to definition" IDE actions, because now we can prove that when we change DBs it's the DB that is wrong because it doesn't correspond to the mock we hacked together.