I know this is an old thread, but for anyone else wondering about this, it's become a more common issue to see mocking difficulties popping up, particularly with the spread of Kotlin (which defaults to final).
For the TLDR for the solution to this problem, here's an example from Javalin:
https://javalin.io/tutorials/mockito-testingIf you use a Kotlin unit testing framework, it will typically support mocking final methods.
Also, just to lend some perspective: I used to feel the same way about "unit" tests - why not connect to a in-memory/test/QA/staging DB!??
But I have since come around:
1) First, terminology. If you're pulling dependencies into the component your testing, you're not unit testing, you're integration testing. Integration testing is invaluable, and catches many bugs unit tests cannot. This is true. Also, as long as we're going over terminology, yes, I'm conflating mocks & stubs, but for this conversation, that should be OK.
2) As I moved around in my career, I found myself writing more and more complicated application-level logic (business logic). Unit tests are invaluable for isolating & verifying complicated application-level logic, particularly as let you built up confidence that a certain subset of code behaves a certain way.
3) As an addendum to (2), unit tests are particularly valuable when making last-second updates to complicated business logic, that has existed for a long time, with many authors, some of who have not been around for a while.
It's true, that, at the level of "my system interacting with the DB", unit tests aren't particularly useful.
But at the level of "my complicated application logic, as required by product managers, and sometimes by *law*" is following the correct logic, canonical, isolated, unit tests are very useful. Particularly when it's not just the DB is a source of data for the logic - it's often the DB, and several other services, all of which depend on their own DBs, etc. And you don't necessarily want to re-design the whole code, possibly breaking that logic, without a good set of tests for that code. So "Re-write all that code so you can easily mock" isn't really a great option, sometimes.
You do *also* need integration level testing, because mocks are, in fact, generally useless verifying your queries, connection pooling, etc are all set up correctly. But in non-trivial applications, there is often a lot of code that lives outside of the code that is retrieving data from the DB. And sometimes it's nice to figure out what's wrong with that code, separate from the DB.
Just wanted to add a view from the other side of things.