GMock: Complete C++ Mocking Guide with Google Mock

GMock: Complete C++ Mocking Guide with Google Mock

Google Mock (GMock) is the mocking library bundled with Google Test. It lets you define mock objects from interfaces, set expectations on method calls, control return values, and verify interactions — all within your existing gtest suite. This guide covers everything from basic MOCK_METHOD to advanced argument matching.


Why Mocking?

Unit tests should test one unit of code in isolation. When a class depends on a database, HTTP client, or file system, you have two problems:

  1. The dependency makes tests slow and flaky
  2. You can't control what the dependency returns

Mocking solves both: replace the real dependency with a mock that you control. The mock records calls and lets you assert interactions.


Setup

GMock is bundled with Google Test — no separate install needed.

# CMakeLists.txt
include(FetchContent)
FetchContent_Declare(
    googletest
    URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip
)
FetchContent_MakeAvailable(googletest)

add_executable(tests tests/test_order_service.cpp)
target_link_libraries(tests PRIVATE
    mylib
    GTest::gtest_main
    GTest::gmock_main  # add this
)

Creating a Mock

GMock mocks are based on abstract interfaces (virtual functions).

Step 1: Define the Interface

// include/database.h
class Database {
public:
    virtual ~Database() = default;
    virtual bool connect(const std::string& host, int port) = 0;
    virtual std::vector<Row> query(const std::string& sql) = 0;
    virtual int execute(const std::string& sql) = 0;
    virtual void disconnect() = 0;
};

Step 2: Create the Mock

// tests/mock_database.h
#include <gmock/gmock.h>
#include "database.h"

class MockDatabase : public Database {
public:
    MOCK_METHOD(bool, connect, (const std::string& host, int port), (override));
    MOCK_METHOD(std::vector<Row>, query, (const std::string& sql), (override));
    MOCK_METHOD(int, execute, (const std::string& sql), (override));
    MOCK_METHOD(void, disconnect, (), (override));
};

MOCK_METHOD(return_type, method_name, (arg_types), (qualifiers)) — that's it.

Step 3: Use in Tests

// tests/test_order_service.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "mock_database.h"
#include "order_service.h"

using ::testing::Return;
using ::testing::_;

class OrderServiceTest : public ::testing::Test {
protected:
    MockDatabase mock_db;
    std::unique_ptr<OrderService> service;
    
    void SetUp() override {
        service = std::make_unique<OrderService>(&mock_db);
    }
};

TEST_F(OrderServiceTest, CreatesOrderSuccessfully) {
    // Set up expectations
    EXPECT_CALL(mock_db, execute(::testing::HasSubstr("INSERT INTO orders")))
        .WillOnce(Return(1));  // returns 1 row affected
    
    // Act
    bool result = service->create_order(Order{"widget", 2, 9.99});
    
    // Assert
    EXPECT_TRUE(result);
    // GMock automatically verifies execute() was called with the right SQL
}

EXPECT_CALL Syntax

EXPECT_CALL(mock_object, method_name(matchers))
    .Times(n)
    .WillOnce(action)
    .WillRepeatedly(action);

Times

EXPECT_CALL(mock_db, disconnect()).Times(1);   // exactly once
EXPECT_CALL(mock_db, disconnect()).Times(0);   // never called
EXPECT_CALL(mock_db, disconnect()).Times(::testing::AtLeast(1));
EXPECT_CALL(mock_db, disconnect()).Times(::testing::AtMost(3));
EXPECT_CALL(mock_db, disconnect()).Times(::testing::Between(2, 4));
EXPECT_CALL(mock_db, disconnect());            // Times(1) is default

Return Values

EXPECT_CALL(mock_db, connect(_, _))
    .WillOnce(Return(true));

EXPECT_CALL(mock_db, query(_))
    .WillOnce(Return(std::vector<Row>{row1, row2}));

// Multiple sequential calls
EXPECT_CALL(mock_db, connect(_, _))
    .WillOnce(Return(false))
    .WillOnce(Return(true));  // first call fails, second succeeds

// Always return the same value
EXPECT_CALL(mock_db, connect(_, _))
    .WillRepeatedly(Return(true));

Ordered Expectations

::testing::InSequence seq;  // RAII — enforces order within scope

EXPECT_CALL(mock_db, connect(_, _)).WillOnce(Return(true));
EXPECT_CALL(mock_db, query(_)).WillOnce(Return(rows));
EXPECT_CALL(mock_db, disconnect());

// Calls must happen in this order — out-of-order = test failure
service->fetch_data();

Argument Matchers

Matchers specify what arguments are acceptable.

Built-in Matchers

using namespace ::testing;

// Exact match
EXPECT_CALL(mock, foo(42));
EXPECT_CALL(mock, foo("hello"));

// Wildcard
EXPECT_CALL(mock, foo(_));  // any argument

// Comparison
EXPECT_CALL(mock, foo(Gt(5)));   // > 5
EXPECT_CALL(mock, foo(Lt(10)));  // < 10
EXPECT_CALL(mock, foo(Ge(5)));   // >= 5
EXPECT_CALL(mock, foo(Le(10)));  // <= 10
EXPECT_CALL(mock, foo(Ne(0)));   // != 0

// String matchers
EXPECT_CALL(mock, foo(HasSubstr("INSERT")));
EXPECT_CALL(mock, foo(StartsWith("SELECT")));
EXPECT_CALL(mock, foo(EndsWith(";")));
EXPECT_CALL(mock, foo(MatchesRegex("SELECT .* FROM users")));

// Pointer/reference
EXPECT_CALL(mock, foo(IsNull()));
EXPECT_CALL(mock, foo(NotNull()));
EXPECT_CALL(mock, foo(Ref(some_var)));  // same reference

// Container
EXPECT_CALL(mock, foo(IsEmpty()));
EXPECT_CALL(mock, foo(SizeIs(3)));
EXPECT_CALL(mock, foo(Contains(42)));
EXPECT_CALL(mock, foo(ElementsAre(1, 2, 3)));
EXPECT_CALL(mock, foo(UnorderedElementsAre(3, 1, 2)));

// Composing
EXPECT_CALL(mock, foo(AllOf(Gt(5), Lt(20))));    // AND
EXPECT_CALL(mock, foo(AnyOf(Lt(0), Gt(100))));   // OR
EXPECT_CALL(mock, foo(Not(Eq(0))));               // NOT

Multiple Arguments

// Match first arg, wildcard for second
EXPECT_CALL(mock_db, connect("prod-db.company.com", _))
    .WillOnce(Return(true));

// Match both arguments
EXPECT_CALL(mock_db, connect("prod-db.company.com", 5432))
    .WillOnce(Return(true));

Actions

Control what the mock does when called.

Return Values

EXPECT_CALL(mock, method(_)).WillOnce(Return(42));
EXPECT_CALL(mock, method(_)).WillOnce(ReturnRef(some_ref));
EXPECT_CALL(mock, method(_)).WillOnce(ReturnNull());

Set Output Arguments

EXPECT_CALL(mock, read_data(_, _))
    .WillOnce(DoAll(
        SetArgPointee<0>(expected_data),   // set first arg (output pointer)
        Return(true)
    ));

Throw Exceptions

EXPECT_CALL(mock_db, connect(_, _))
    .WillOnce(Throw(std::runtime_error("Connection refused")));

// Test that your code handles this
EXPECT_THROW(service->connect(), ServiceUnavailableException);

Custom Actions with Lambdas

EXPECT_CALL(mock_db, query(_))
    .WillOnce(::testing::Invoke([](const std::string& sql) -> std::vector<Row> {
        // Validate the SQL query
        EXPECT_THAT(sql, HasSubstr("WHERE user_id ="));
        return {Row{"alice", "alice@example.com"}};
    }));

Capturing Arguments

Inspect what arguments were passed to the mock:

std::string captured_sql;

EXPECT_CALL(mock_db, execute(_))
    .WillOnce(::testing::DoAll(
        ::testing::SaveArg<0>(&captured_sql),
        Return(1)
    ));

service->create_user("alice", "alice@example.com");

// Now inspect the SQL that was generated
EXPECT_THAT(captured_sql, HasSubstr("alice@example.com"));
EXPECT_THAT(captured_sql, StartsWith("INSERT INTO users"));

Verifying Interactions

GMock automatically verifies expectations at the end of each test. But you can verify explicitly:

TEST_F(OrderServiceTest, DisconnectsOnShutdown) {
    EXPECT_CALL(mock_db, disconnect()).Times(1);
    
    service->shutdown();
    
    // Explicit verification (optional — happens automatically in TearDown)
    ::testing::Mock::VerifyAndClearExpectations(&mock_db);
}

To verify a mock never received unexpected calls:

// Any call to mock_db that wasn't explicitly expected will fail the test
// This is the default behavior — no extra code needed

Nice, Strict, and Naggy Mocks

// Default (naggy): warns on unexpected calls, doesn't fail
MockDatabase mock_db;

// Nice: silently ignores unexpected calls
::testing::NiceMock<MockDatabase> nice_mock;

// Strict: fails on any unexpected call
::testing::StrictMock<MockDatabase> strict_mock;

Use NiceMock when you want to focus on specific interactions and ignore everything else. Use StrictMock when any unexpected interaction is a bug.


Mocking Non-Virtual Functions

GMock requires virtual functions. For non-virtual code (e.g., legacy C++ or performance-critical classes), use template injection:

// Production code — no virtual
class RealDatabase {
public:
    bool connect(const std::string& host, int port);
    std::vector<Row> query(const std::string& sql);
};

// Make the service templated
template<typename DB>
class OrderService {
public:
    explicit OrderService(DB* db) : db_(db) {}
    
    bool create_order(Order order) {
        return db_->execute("INSERT INTO orders ...") > 0;
    }
    
private:
    DB* db_;
};

// In tests: use a mock class (no interface needed)
class MockDatabase {
public:
    MOCK_METHOD(bool, connect, (const std::string&, int));
    MOCK_METHOD(std::vector<Row>, query, (const std::string&));
    MOCK_METHOD(int, execute, (const std::string&));
};

TEST(OrderServiceTest, CreateOrder) {
    MockDatabase mock;
    OrderService<MockDatabase> service(&mock);
    
    EXPECT_CALL(mock, execute(_)).WillOnce(Return(1));
    EXPECT_TRUE(service.create_order(Order{}));
}

ON_CALL: Default Behavior Without Strict Expectations

EXPECT_CALL expects an exact number of calls. ON_CALL sets default behavior without strict call count requirements:

// Set default return value without requiring the call
ON_CALL(mock_db, connect(_, _))
    .WillByDefault(Return(true));

// Now connect() always returns true when called, without a strict expectation
// Useful in SetUp() for common defaults

Combine ON_CALL defaults with specific EXPECT_CALL overrides:

void SetUp() override {
    // Default behavior for all tests
    ON_CALL(mock_db, connect(_, _)).WillByDefault(Return(true));
    ON_CALL(mock_db, disconnect()).WillByDefault(Return());
}

TEST_F(OrderServiceTest, HandlesConnectionFailure) {
    // Override default for this specific test
    EXPECT_CALL(mock_db, connect(_, _)).WillOnce(Return(false));
    
    EXPECT_FALSE(service->connect());
}

Complete Example: Testing a Payment Service

// payment_service.h
class PaymentGateway {
public:
    virtual ~PaymentGateway() = default;
    virtual ChargeResult charge(const std::string& card_token, int amount_cents) = 0;
    virtual RefundResult refund(const std::string& charge_id) = 0;
};

class PaymentService {
public:
    explicit PaymentService(PaymentGateway* gateway);
    bool process_payment(const Order& order);
    bool refund_order(const std::string& order_id);
};

// tests/test_payment_service.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "payment_gateway.h"
#include "payment_service.h"

class MockPaymentGateway : public PaymentGateway {
public:
    MOCK_METHOD(ChargeResult, charge, 
                (const std::string& card_token, int amount_cents), (override));
    MOCK_METHOD(RefundResult, refund, 
                (const std::string& charge_id), (override));
};

class PaymentServiceTest : public ::testing::Test {
protected:
    ::testing::NiceMock<MockPaymentGateway> gateway;
    std::unique_ptr<PaymentService> service;
    
    void SetUp() override {
        service = std::make_unique<PaymentService>(&gateway);
    }
};

TEST_F(PaymentServiceTest, ProcessesPaymentSuccessfully) {
    ChargeResult success{.charge_id = "ch_123", .success = true};
    EXPECT_CALL(gateway, charge("tok_visa", 2000))
        .WillOnce(Return(success));
    
    Order order{.card_token = "tok_visa", .amount_cents = 2000};
    EXPECT_TRUE(service->process_payment(order));
}

TEST_F(PaymentServiceTest, ReturnsFalseOnDeclinedCharge) {
    ChargeResult declined{.charge_id = "", .success = false, .error = "card_declined"};
    EXPECT_CALL(gateway, charge(_, _)).WillOnce(Return(declined));
    
    EXPECT_FALSE(service->process_payment(Order{}));
}

TEST_F(PaymentServiceTest, DoesNotChargeZeroAmount) {
    EXPECT_CALL(gateway, charge(_, _)).Times(0);  // should not call gateway
    
    Order zero_order{.amount_cents = 0};
    EXPECT_FALSE(service->process_payment(zero_order));
}

TEST_F(PaymentServiceTest, RefundsSuccessfully) {
    RefundResult refunded{.success = true};
    EXPECT_CALL(gateway, refund("ch_123")).WillOnce(Return(refunded));
    
    EXPECT_TRUE(service->refund_order("order_abc"));
}

TEST_F(PaymentServiceTest, ThrowsOnGatewayException) {
    EXPECT_CALL(gateway, charge(_, _))
        .WillOnce(Throw(std::runtime_error("Gateway timeout")));
    
    EXPECT_THROW(service->process_payment(Order{}), PaymentException);
}

Next Steps

  • Combine with gtest fixtures — see the Google Test tutorial for fixture patterns
  • Use with Catch2 — GMock matchers work with Catch2 via REQUIRE_THAT
  • Try CMock for C (non-C++) embedded projects — see the CMock and Unity guide
  • Add memory checks — run your mock tests under AddressSanitizer (see memory testing guide)

Read more