You should define an interface that contains all the database methods in your class. Then, ensure your existing database class implements that interface.
Now you have an interface, you can either mock the class or develop a stub class for testing. The stub class can just print the SQL, or whatever you want. A mock class is more powerful and can be used to ensure your business logic is working correctly.
The final step is to ensure that anywhere that uses the database accepts your interface in the constructor. E.g.
public class ClassThatUsesTheDatabase {
public ClassThatUsesTheDatabase(DatabaseProvider provider) {
//...
}
}
where DatabaseProvider
is your interface. This allows you to test ClassThatUsesTheDatabase
with your stub or mock. In production, you would construct this class with your concrete implementation.
In my opinion, this is the only sane way to write applications that rely on external resources.
After re-reading your question, I'm concerned about the following paragraph:
Disclaimer: Please no solutions like "Parameterize your class." I want my constructors to have very few parameters, I don't want to have to specify everything whenever I call it. The test classes are second class citizens in my application and they should have little to no effect on the actual classes / the actual development.
Test classes are not second class citizens. They are just as important as your production code, if you're serious about code quality. And yes, you very often have to design your production code to make it suitable for unit testing. This is unavoidable. The benefits are huge, however.