Mocking the Cloud Spanner C++ Client with Google Mock
In this document we describe how to write unit tests that mockgoogle::cloud::spanner::Clientusing Google Mock. This document assumes the reader is familiar with the Google Test and Google Mock frameworks and with the Cloud Spanner C++ Client.
Mocking a successful ExecuteQuery
First include the headers for the Cloud Spanner Client, the mocking class, and the Google Mock framework.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-09-04 UTC."],[[["\u003cp\u003eThe latest version of the Cloud Spanner C++ Client documentation is version 2.37.0-rc, with a list provided of previous versions available for reference.\u003c/p\u003e\n"],["\u003cp\u003eThis document demonstrates how to mock \u003ccode\u003egoogle::cloud::spanner::Client\u003c/code\u003e using Google Mock to write unit tests for the Cloud Spanner C++ client.\u003c/p\u003e\n"],["\u003cp\u003eMocking \u003ccode\u003egoogle::cloud::spanner::Connection\u003c/code\u003e allows you to simulate a stream of results from a \u003ccode\u003egoogle::cloud::spanner::RowStream\u003c/code\u003e to test client behavior.\u003c/p\u003e\n"],["\u003cp\u003eA mock \u003ccode\u003egoogle::cloud::spanner::RowStream\u003c/code\u003e source is created, defining column names and types, then set up to return mocked results, one value at a time.\u003c/p\u003e\n"],["\u003cp\u003eThe process involves creating a mock \u003ccode\u003egoogle::cloud::spanner::Connection\u003c/code\u003e, setting up the mock source, mocking the \u003ccode\u003eExecuteQuery\u003c/code\u003e behavior, and then using the client to make requests and verify the results.\u003c/p\u003e\n"]]],[],null,["Version latestkeyboard_arrow_down\n\n- [2.42.0-rc (latest)](/cpp/docs/reference/spanner/latest/spanner-mocking)\n- [2.41.0](/cpp/docs/reference/spanner/2.41.0/spanner-mocking)\n- [2.40.0](/cpp/docs/reference/spanner/2.40.0/spanner-mocking)\n- [2.39.0](/cpp/docs/reference/spanner/2.39.0/spanner-mocking)\n- [2.38.0](/cpp/docs/reference/spanner/2.38.0/spanner-mocking)\n- [2.37.0](/cpp/docs/reference/spanner/2.37.0/spanner-mocking)\n- [2.36.0](/cpp/docs/reference/spanner/2.36.0/spanner-mocking)\n- [2.35.0](/cpp/docs/reference/spanner/2.35.0/spanner-mocking)\n- [2.34.0](/cpp/docs/reference/spanner/2.34.0/spanner-mocking)\n- [2.33.0](/cpp/docs/reference/spanner/2.33.0/spanner-mocking)\n- [2.32.0](/cpp/docs/reference/spanner/2.32.0/spanner-mocking)\n- [2.31.0](/cpp/docs/reference/spanner/2.31.0/spanner-mocking)\n- [2.30.0](/cpp/docs/reference/spanner/2.30.0/spanner-mocking)\n- [2.29.0](/cpp/docs/reference/spanner/2.29.0/spanner-mocking)\n- [2.28.0](/cpp/docs/reference/spanner/2.28.0/spanner-mocking)\n- [2.27.0](/cpp/docs/reference/spanner/2.27.0/spanner-mocking)\n- [2.26.0](/cpp/docs/reference/spanner/2.26.0/spanner-mocking)\n- [2.25.1](/cpp/docs/reference/spanner/2.25.1/spanner-mocking)\n- [2.24.0](/cpp/docs/reference/spanner/2.24.0/spanner-mocking)\n- [2.23.0](/cpp/docs/reference/spanner/2.23.0/spanner-mocking)\n- [2.22.1](/cpp/docs/reference/spanner/2.22.1/spanner-mocking)\n- [2.21.0](/cpp/docs/reference/spanner/2.21.0/spanner-mocking)\n- [2.20.0](/cpp/docs/reference/spanner/2.20.0/spanner-mocking)\n- [2.19.0](/cpp/docs/reference/spanner/2.19.0/spanner-mocking)\n- [2.18.0](/cpp/docs/reference/spanner/2.18.0/spanner-mocking)\n- [2.17.0](/cpp/docs/reference/spanner/2.17.0/spanner-mocking)\n- [2.16.0](/cpp/docs/reference/spanner/2.16.0/spanner-mocking)\n- [2.15.1](/cpp/docs/reference/spanner/2.15.1/spanner-mocking)\n- [2.14.0](/cpp/docs/reference/spanner/2.14.0/spanner-mocking)\n- [2.13.0](/cpp/docs/reference/spanner/2.13.0/spanner-mocking)\n- [2.12.0](/cpp/docs/reference/spanner/2.12.0/spanner-mocking)\n- [2.11.0](/cpp/docs/reference/spanner/2.11.0/spanner-mocking) \n\nMocking the Cloud Spanner C++ Client with Google Mock\n=====================================================\n\nIn this document we describe how to write unit tests that mock [`google::cloud::spanner::Client`](/cpp/docs/reference/spanner/latest/classgoogle_1_1cloud_1_1spanner_1_1Client) using Google Mock. This document assumes the reader is familiar with the Google Test and Google Mock frameworks and with the Cloud Spanner C++ Client.\n\n### Mocking a successful ExecuteQuery\n\nFirst include the headers for the Cloud Spanner Client, the mocking class, and the Google Mock framework. \n\n #include \"google/cloud/spanner/client.h\"\n #include \"google/cloud/spanner/mocks/mock_spanner_connection.h\"\n #include \"google/cloud/spanner/mocks/row.h\"\n #include \u003cgoogle/protobuf/text_format.h\u003e\n #include \u003cgmock/gmock.h\u003e\n\nThe example uses a number of aliases to save typing and improve readability: \n\n using ::testing::Return;\n namespace spanner = ::google::cloud::spanner;\n\nCreate a mocking object for [`google::cloud::spanner::Connection`](/cpp/docs/reference/spanner/latest/classgoogle_1_1cloud_1_1spanner_1_1Connection): \n\n auto conn = std::make_shared\u003cgoogle::cloud::spanner_mocks::MockConnection\u003e();\n\nWe will setup this mock in a second, but first let's look at how it is used to create a [`google::cloud::spanner::Client`](/cpp/docs/reference/spanner/latest/classgoogle_1_1cloud_1_1spanner_1_1Client) object: \n\n spanner::Client client(conn);\n\nOnce the client is created you can make calls on the client as usual: \n\n auto rows = client.ExecuteQuery(\n spanner::SqlStatement(\"SELECT Id, Greeting FROM Greetings\"));\n\nAnd then verify the results meet your expectations: \n\n int count = 0;\n using RowType = std::tuple\u003cstd::int64_t, std::string\u003e;\n for (auto const& row : spanner::StreamOf\u003cRowType\u003e(rows)) {\n ASSERT_TRUE(row);\n auto expected_id = ++count;\n EXPECT_EQ(expected_id, std::get\u003c0\u003e(*row));\n EXPECT_EQ(\"Hello World\", std::get\u003c1\u003e(*row));\n }\n\nAll of this depends on creating a [`google::cloud::spanner::RowStream`](/cpp/docs/reference/spanner/latest/classgoogle_1_1cloud_1_1spanner_1_1RowStream) that simulates the stream of results you want. To do so, you need to mock a source that streams [`google::cloud::spanner::Row`](/cpp/docs/reference/spanner/latest/classgoogle_1_1cloud_1_1spanner_1_1Row)s: \n\n auto source =\n std::make_unique\u003cgoogle::cloud::spanner_mocks::MockResultSetSource\u003e();\n\nThe source must define the names and types of the columns returned by the query: \n\n auto constexpr kText = R\"pb(\n row_type: {\n fields: {\n name: \"Id\",\n type: { code: INT64 }\n }\n fields: {\n name: \"Greeting\",\n type: { code: STRING }\n }\n })pb\";\n google::spanner::v1::ResultSetMetadata metadata;\n ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kText, &metadata));\n EXPECT_CALL(*source, Metadata()).WillRepeatedly(Return(metadata));\n\nAnd then setup the mock to return the results. Note that the results are returned one value at a time, even if a row contains multiple values. \n\n EXPECT_CALL(*source, NextRow())\n .WillOnce(Return(google::cloud::spanner_mocks::MakeRow(\n {{\"Id\", spanner::Value(1)},\n {\"Greeting\", spanner::Value(\"Hello World\")}})))\n .WillOnce(Return(google::cloud::spanner_mocks::MakeRow(\n {{\"Id\", spanner::Value(2)},\n {\"Greeting\", spanner::Value(\"Hello World\")}})))\n\nNote that the last value in the stream is indicated by an absl::optional without a value: \n\n .WillOnce(Return(spanner::Row()));\n\nOnce the `source` has been created and its behavior mocked, you mock the behavior for `ExecuteQuery`: \n\n EXPECT_CALL(*conn, ExecuteQuery)\n .WillOnce([&source](spanner::Connection::SqlParams const&)\n -\u003e spanner::RowStream {\n return spanner::RowStream(std::move(source));\n });\n\n### Full Listing\n\nFinally we present the full code for this example: \n\n\n #include \"google/cloud/spanner/client.h\"\n #include \"google/cloud/spanner/mocks/mock_spanner_connection.h\"\n #include \"google/cloud/spanner/mocks/row.h\"\n #include \u003cgoogle/protobuf/text_format.h\u003e\n #include \u003cgmock/gmock.h\u003e\n\n namespace {\n\n using ::testing::Return;\n namespace spanner = ::google::cloud::spanner;\n\n TEST(MockSpannerClient, SuccessfulExecuteQuery) {\n // Create a mock object to stream the results of a ExecuteQuery.\n auto source =\n std::make_unique\u003cgoogle::cloud::spanner_mocks::MockResultSetSource\u003e();\n\n // Setup the return type of the ExecuteQuery results:\n auto constexpr kText = R\"pb(\n row_type: {\n fields: {\n name: \"Id\",\n type: { code: INT64 }\n }\n fields: {\n name: \"Greeting\",\n type: { code: STRING }\n }\n })pb\";\n google::spanner::v1::ResultSetMetadata metadata;\n ASSERT_TRUE(google::protobuf::TextFormat::ParseFromString(kText, &metadata));\n EXPECT_CALL(*source, Metadata()).WillRepeatedly(Return(metadata));\n\n // Setup the mock source to return some values:\n EXPECT_CALL(*source, NextRow())\n .WillOnce(Return(google::cloud::spanner_mocks::MakeRow(\n {{\"Id\", spanner::Value(1)},\n {\"Greeting\", spanner::Value(\"Hello World\")}})))\n .WillOnce(Return(google::cloud::spanner_mocks::MakeRow(\n {{\"Id\", spanner::Value(2)},\n {\"Greeting\", spanner::Value(\"Hello World\")}})))\n .WillOnce(Return(spanner::Row()));\n\n // Create a mock for `spanner::Connection`:\n auto conn = std::make_shared\u003cgoogle::cloud::spanner_mocks::MockConnection\u003e();\n\n // Setup the connection mock to return the results previously setup:\n EXPECT_CALL(*conn, ExecuteQuery)\n .WillOnce([&source](spanner::Connection::SqlParams const&)\n -\u003e spanner::RowStream {\n return spanner::RowStream(std::move(source));\n });\n\n // Create a client with the mocked connection:\n spanner::Client client(conn);\n\n // Make the request and verify the expected results:\n auto rows = client.ExecuteQuery(\n spanner::SqlStatement(\"SELECT Id, Greeting FROM Greetings\"));\n\n int count = 0;\n using RowType = std::tuple\u003cstd::int64_t, std::string\u003e;\n for (auto const& row : spanner::StreamOf\u003cRowType\u003e(rows)) {\n ASSERT_TRUE(row);\n auto expected_id = ++count;\n EXPECT_EQ(expected_id, std::get\u003c0\u003e(*row));\n EXPECT_EQ(\"Hello World\", std::get\u003c1\u003e(*row));\n }\n }\n\n } // namespace"]]