【C/C++】Gtest + GMock 简单使用示例
本文主要用于介绍一个完整的 GTest + GMock 使用示例,涵盖了接口定义、Mock 类实现、被测试类、以及单元测试代码,展示了如何使用 GMock 模拟依赖并进行行为验证。
项目结构
gtest_gmock_demo/
├── CMakeLists.txt
├── include/
│ └── database.h
| └── user_service.h
├── src/
│ └── user_service.cpp
├── test/
│ ├── user_service_test.cpp
│ └── mock_database.h
1. 接口定义:include/database.h
#pragma once
#include <string>class IDatabase {
public:virtual ~IDatabase() = default;virtual bool connect(const std::string& db_uri) = 0;virtual bool save_user(const std::string& username, int age) = 0;
};
2. 业务实现:src/user_service.cpp
// include/user_service.h
#pragma once#include "database.h"class UserService {
public:UserService(IDatabase *db);bool register_user(const std::string& username, int age);private:IDatabase *db_;
};
// src/user_service.cpp
#include "user_service.h"UserService::UserService(IDatabase *db) : db_(db) {}bool UserService::register_user(const std::string& username, int age) {if (db_ == nullptr || username.empty() || age <= 0) {return false;}return db_->save_user(username, age);
}
3. GMock 模拟类:test/mock_database.h
#pragma once
#include "database.h"
#include <gmock/gmock.h>class MockDatabase : public IDatabase {
public:MOCK_METHOD(bool, connect, (const std::string& db_uri), (override));MOCK_METHOD(bool, save_user, (const std::string& username, int age), (override));
};
4. 单元测试:test/user_service_test.cpp
#include "mock_database.h"
#include "user_service.h"
#include <gtest/gtest.h>TEST(UserServiceTest, RegisterUserSuccess) {MockDatabase mock_db;UserService service(&mock_db);// 设定期望:save_user 被调用一次,参数为 "alice", 30,返回 trueEXPECT_CALL(mock_db, save_user("alice", 30)).Times(1).WillOnce(::testing::Return(true));EXPECT_TRUE(service.register_user("alice", 30));
}TEST(UserServiceTest, RegisterUserFail_EmptyName) {MockDatabase mock_db;UserService service(&mock_db);// 不应调用 save_userEXPECT_CALL(mock_db, save_user(::testing::_, ::testing::_)).Times(0);EXPECT_FALSE(service.register_user("", 25));
}TEST(UserServiceTest, RegisterUserFail_NegativeAge) {MockDatabase mock_db;UserService service(&mock_db);EXPECT_CALL(mock_db, save_user(::testing::_, ::testing::_)).Times(0);EXPECT_FALSE(service.register_user("bob", -10));
}
CMake 配置:CMakeLists.txt
cmake_minimum_required(VERSION 3.14)project(GTestGMockDemo)set(CMAKE_CXX_STANDARD 17)enable_testing()
include_directories(include lib)
link_directories(lib) # 需要自己之前已经编译过googletest,并将gmock/gtest的.a放到lib中add_executable(unit_testssrc/user_service.cpptest/user_service_test.cpp
)target_link_libraries(unit_testsgtestgmockgtest_mainpthread
)add_test(NAME AllTests COMMAND unit_tests)
编译和运行测试
mkdir build && cd build
cmake ..
make
./unit_tests
相关知识点
模块 | 说明 |
---|---|
IDatabase | 依赖接口,用于隔离测试 |
MockDatabase | GMock 自动生成桩代码 |
UserService | 被测试的业务逻辑 |
EXPECT_CALL | 验证函数是否按预期调用 |