From 6a43c8f6c642b73d89652ccc8814a5f6cce57c1b Mon Sep 17 00:00:00 2001 From: John Maguire Date: Tue, 2 Mar 2010 13:35:39 +0000 Subject: [PATCH] Refactor LibraryBackendTest to make it easier to write tests. --- tests/librarybackend_test.cpp | 117 +++++++++++++++++++++++++++------- 1 file changed, 94 insertions(+), 23 deletions(-) diff --git a/tests/librarybackend_test.cpp b/tests/librarybackend_test.cpp index 6a7fdc681..da8b5be9d 100644 --- a/tests/librarybackend_test.cpp +++ b/tests/librarybackend_test.cpp @@ -11,6 +11,7 @@ #include using ::testing::_; +using ::testing::AtMost; using ::testing::Invoke; using ::testing::Return; @@ -22,10 +23,12 @@ void PrintTo(const ::QString& str, std::ostream& os) { class LibraryBackendTest : public ::testing::Test { protected: - LibraryBackendTest() { + LibraryBackendTest() + : current_result_(0) { } virtual void SetUp() { + // Owned by QSqlDatabase. driver_ = new MockSqlDriver; // DB connect calls. EXPECT_CALL(*driver_, open(_, _, _, _, _, _)).WillOnce(Return(true)); @@ -60,17 +63,73 @@ class LibraryBackendTest : public ::testing::Test { reinterpret_cast(QThread::currentThread()))); } + // Call this to mock a single query with one row of results. + void ExpectQuery(const QString& query, + const QList& bind_values, + const QMap& named_bind_values, + const QList& columns) { + // Owned by QSqlDatabase. + current_result_ = new MockSqlResult(driver_); + EXPECT_CALL(*driver_, createResult()). + WillOnce(Return(current_result_)); + + // Query string is set. + EXPECT_CALL(*current_result_, reset(QString(query))).WillOnce( + DoAll( + Invoke(current_result_, &MockSqlResult::hackSetActive), + Return(true))); + // Query is executed. + EXPECT_CALL(*current_result_, exec()).WillOnce(Return(true)); + + // Values are bound. + for (int i = 0; i < bind_values.size(); ++i) { + ExpectBind(i, bind_values[i]); + } + for (QMap::const_iterator it = named_bind_values.begin(); + it != named_bind_values.end(); ++it) { + ExpectBind(it.key(), it.value()); + } + + // One row is fetched. + EXPECT_CALL(*current_result_, fetch(1)).WillOnce( + DoAll( + Invoke(current_result_, &MockSqlResult::setAt), + Return(true))); + // Tries to fetch second row but we say we do not have any more rows. + // Can be called 0-1 times. This catches the case where a query is only expected + // to have one row so QSqlQuery::next() is only called once. + EXPECT_CALL(*current_result_, fetch(2)).Times(AtMost(1)).WillOnce(Return(false)); + + // Expect data() calls for each column. + ExpectData(columns); + } + + void ExpectBind(int index, const QVariant& value) { + EXPECT_CALL(*current_result_, bindValue(index, value, _)); + } + + void ExpectBind(const QString& bind, const QVariant& value) { + EXPECT_CALL(*current_result_, bindValue(bind, value, _)); + } + + void ExpectData(const QList& columns) { + for (int i = 0; i < columns.size(); ++i) { + EXPECT_CALL(*current_result_, data(i)).WillRepeatedly( + Return(columns[i])).RetiresOnSaturation(); + } + } + MockSqlDriver* driver_; scoped_ptr backend_; -}; -MATCHER(Printer, "") { qDebug() << arg; return true; } + MockSqlResult* current_result_; +}; TEST_F(LibraryBackendTest, DatabaseInitialises) { } -TEST_F(LibraryBackendTest, GetSongs) { +TEST_F(LibraryBackendTest, GetSongsSuccessfully) { const char* query = "SELECT ROWID, title, album, artist, albumartist, composer, " "track, disc, bpm, year, genre, comment, compilation, " @@ -79,32 +138,44 @@ TEST_F(LibraryBackendTest, GetSongs) { " FROM songs " "WHERE (compilation = 0 AND sampler = 0) AND artist = ?" " AND album = ?"; - MockSqlResult* result = new MockSqlResult(driver_); - EXPECT_CALL(*driver_, createResult()). - WillOnce(Return(result)); - EXPECT_CALL(*result, reset(QString(query))).WillOnce( - DoAll( - Invoke(result, &MockSqlResult::hackSetActive), - Return(true))); - - EXPECT_CALL(*result, bindValue(0, QVariant("foo"), _)); - EXPECT_CALL(*result, bindValue(1, QVariant("bar"), _)); - - EXPECT_CALL(*result, exec()).WillOnce(Return(true)); - EXPECT_CALL(*result, fetch(1)).WillOnce( - DoAll( - Invoke(result, &MockSqlResult::setAt), - Return(true))); - EXPECT_CALL(*result, fetch(2)).WillOnce(Return(false)); + QList bind_values; + bind_values << "foo"; + bind_values << "bar"; + QList columns; for (int i = 0; i < 24; ++i) { // Fill every column with 42. - EXPECT_CALL(*result, data(i)).WillRepeatedly( - Return(QVariant(42))).RetiresOnSaturation(); + columns << 42; } + ExpectQuery(query, bind_values, QMap(), columns); + SongList songs = backend_->GetSongs("foo", "bar"); ASSERT_EQ(1, songs.length()); EXPECT_EQ(42, songs[0].length()); EXPECT_EQ(42, songs[0].id()); } + +TEST_F(LibraryBackendTest, GetSongByIdSuccessfully) { + const char* query = + "SELECT ROWID, title, album, artist, albumartist, composer, " + "track, disc, bpm, year, genre, comment, compilation, " + "length, bitrate, samplerate, directory, filename, " + "mtime, ctime, filesize, sampler, art_automatic, art_manual" + " FROM songs " + "WHERE ROWID = :id"; + QMap bind_values; + bind_values[":id"] = 42; + + QList columns; + for (int i = 0; i < 24; ++i) { + // Fill every column with 42. + columns << 42; + } + + ExpectQuery(query, QList(), bind_values, columns); + + Song song = backend_->GetSongById(42); + EXPECT_EQ(42, song.length()); + EXPECT_EQ(42, song.id()); +}