C++中可使用Google Test/Gmock Mock调用std::thread的函数吗?
错误根因
该报错是C++ std::thread的原生机制导致,和gmock不存在兼容冲突:C++标准规定,std::thread对象析构时如果仍处于可汇合(joinable)状态,会直接调用std::terminate终止程序。你的测试用例仅调用了创建线程的myfun(),未执行负责线程汇合的final(),测试用例结束后类实例内的thread_id成员析构时仍为可汇合状态,因此触发了终止逻辑。
gtest/gmock本身完全支持多线程测试,只要遵守std::thread的生命周期规则即可,两类解决方案如下:
方案1:无需mock std::thread,直接修复现有测试
在测试用例中补充线程汇合逻辑,保证线程资源正常回收:
TEST_F(mytest, myfun) { EXPECT_CALL(logger_mock_, Info(LOG001, ::testing::_)); // 期望日志调用 my_class_.myfun(); // 创建线程 my_class_.final(); // 补充调用汇合逻辑 }
如果threadfunction内有需要验证的逻辑,可在join之后补充对应断言。
方案2:mock std::thread,避免真实创建线程
如果测试不需要真实执行线程逻辑,仅需验证线程创建、汇合的调用行为,可以对std::thread做抽象封装后mock:
- 定义线程操作抽象接口
class ThreadInterface { public: virtual ~ThreadInterface() = default; virtual void start(std::function<void()> func) = 0; virtual bool joinable() const = 0; virtual void join() = 0; };
- 实现生产环境用的std::thread封装类
class StdThreadWrapper : public ThreadInterface { private: std::thread thread_; public: void start(std::function<void()> func) override { thread_ = std::thread(std::move(func)); } bool joinable() const override { return thread_.joinable(); } void join() override { if(joinable()) thread_.join(); } };
- 实现测试用mock类
class MockThread : public ThreadInterface { public: MOCK_METHOD(void, start, (std::function<void()>), (override)); MOCK_METHOD(bool, joinable, (), (const, override)); MOCK_METHOD(void, join, (), (override)); };
- 业务类依赖注入抽象接口
生产环境注入StdThreadWrapper实例,测试环境注入MockThread实例,即可验证线程相关调用行为,无需真实创建线程,也不会出现生命周期问题:
class MyClass { public: explicit MyClass(std::unique_ptr<ThreadInterface> thread_ptr) : thread_(std::move(thread_ptr)) {} void myfun() { thread_->start([this]() { threadfunction(); }); logger_.Info(LOG001, "Myfun() is called"); } void final() { if(thread_->joinable()) thread_->join(); } private: std::unique_ptr<ThreadInterface> thread_; Logger logger_; void threadfunction(); };
内容的提问来源于stack exchange,提问作者Ganesh Kulkarni
相关产品推荐
相关产品推荐

