Unit Testing – When to Connect to the Database

databaseunit testing

There are answers to the question on how test classes that connect to a database, e.g. "Should service test classes connect …" and "Unit testing – Database coupled app".

So, in short let's assume you have a class A that needs to connect to a database. Instead of letting A actually connect, you provide A with an interface that A may use to connect. For testing you implement this interface with some stuff – without connecting of course. If class B instantiates A it has to pass a "real" database connection to A. But that means B opens a database connection. That means to test B you inject the connection into B. But B is instantiated in class C and so forth.

So at which point do I have to say "here I fetch data from a database and I will not write a unit test for this piece of code"?

In other words: Somewhere in the code in some class I must call sqlDB.connect() or something similar. How do I test this class?

And is it the same with code that has to deal with a GUI or a file system?


I want to do Unit-Test. Any other kind of test is not related to my question. I know that I will only test one class with it (I so agree with you Kilian). Now, some class has to connect to a DB. If I want to test this class and ask "How do I do this" many say: "Use Dependency Injection!" But that only shifts the problem to another class, doesn't it? So I ask, how do I test the class that really, really establishes the connection?

Bonus question: Some answers here boil down to "Use mock objects!" What does that mean? I mock classes that the class-under-test depend upon. Shall I mock the class-under-test now and actually test the mock (which comes close to the idea of using Template Methods, see below)?

Best Answer

The point of a unit test is to test one class (in fact, it should usually test one method).

This means that when you test class A, you inject a test database into it - something self-written, or a lightning-fast in-memory database, whatever gets the job done.

However, if you test class B, which is a client of A, then usually you mock the entire A object with something else, presumably something that does its job in a primitive, pre-programmed way - without using an actual A object and certainly without using a database (unless A passes the entire database connection back to its caller - but that's so horrible I don't want to think about it). Likewise, when you write a unit test for class C, which is a client of B, you would mock something that takes the role of B, and forget about A altogether.

If you don't do that, it's no longer a unit test, but a system or integration test. Those are very important as well, but a whole different kettle of fish. To begin with, they are usually more effort to set up and run, it isn't practicable to demand to pass them as a precondition to check-ins, etc.

Related Topic