I usually use two approaches.
The code that depends on the database abstraction layer works with IoC and is therefore easily testable with mocks/stubs. You have an IDataAccess or IRepository interface and you test the interactions of your code against it.
The code that actually works against the database (say a class implementing IDataAccess) is tested on its own, usually performing round-trips to the database (insert-retrieve-update-retrieve-delete). Before running every test case the database is recreated or emptied to avoid test cross-talk. This leads to tests requiring a few minutes to run instead of a few seconds, but in my opinion it's important to test the actual database you will use in production. Using a replacement such as in-memory SQLite is not a good choice because it's too different from, for instance, SQL Server.