Using Qt Test and private members
-
Hello everyone
For far too long I have been too lazy to properly using Qt Test in my development process and now I am starting to try to implement it. But I have hit a wall regarding private members.
Let me illustrate with an example with a simple class I have made.class SqlComm : public QObject { Q_OBJECT public: SqlComm(QSqlDatabase _database, QObject* parent = nullptr); void setDatabase(const QString &&host, const QString &&database); void setUser(const QString &&user, const QString &&psswd); void connectToDB(); unsigned int getNextDBSerial(); protected: QSqlDatabase* db; QSqlQuery* query; };
Since I am doing unit testing, my plan is to simplify the testing by making a QSqlDatabase stub, where I can return different results and answers to simulate actual response from the database. But the QSqlDatabase is a private member that I can not access to insert the stub.
I have searched and found different answers:-
Add a define changing private members into public (#define private public)
-
Do not use private members but use protected instead. Subclass my class and raise access level to public.
-
Use interface (I have not entirely understood this one yet)
The two first options I feel is a bit dirty and third one seem overly complicated.
How would you test this class?
Regards
Sebastian -
-
- Why do you even have
QSqlDatabase
as a member? The fact that it is a pointer worries me even more - "Use interface" is one of the possible solutions, the other alternative is to move the private members into a pimpl and just have different versions of the private class for test and production (see https://wiki.qt.io/D-Pointer)
- The easiest and, if you ask me, more robust way to actually test it is to add a test db (a sqlite database file if you don't have a full fledged test db server) to your project and have the test program run off it rather than the production one. It's the only real way to actually test what will happen in production
- Why do you even have
-
Hey VRonin
Thank you for your fast response and input.
@VRonin said in Using Qt Test and private members:
- Why do you even have
QSqlDatabase
as a member? The fact that it is a pointer worries me even more
What is wrong with this approach? Would it be better in your opinion to subclass QSqlDatabase?
Regards
Sebastian - Why do you even have
-
@Aslund said in Using Qt Test and private members:
QSqlDatabase
is a singleton and contains all databases you created. So, why do you need a pointer to a QSqlDatabase?
See https://doc.qt.io/qt-5/qsqldatabase.html// Add database QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL"); db.setHostName("acidalia"); db.setDatabaseName("customdb"); db.setUserName("mojito"); db.setPassword("J0a1m8"); bool ok = db.open(); ... // Here you get your database QSqlDatabase db = QSqlDatabase::database();
-
Hey Jsulm
Thank you for clearing it up. Makes sense now. I missed the fact that QSqlDatabase is a singleton. Rereading the documentation I can also see the following statement.
Warning: It is highly recommended that you do not keep a copy of the QSqlDatabase around as a member of a class, as this will prevent the instance from being correctly cleaned up on shutdown. If you need to access an existing QSqlDatabase, it should be accessed with database(). If you chose to have a QSqlDatabase member variable, this needs to be deleted before the QCoreApplication instance is deleted, otherwise it may lead to undefined behavior.