使用EXPECT_CALL宏抛自定义异常编译失败,求正确代码方案
问题解决与修正代码
错误原因分析
- 类型捕获不匹配:测试用例抛出
CustomException,但catch块捕获的是std::invalid_argument,既会导致异常无法被正确处理,也会在编译阶段引发fmt格式字符串的类型转换冲突。 - 模板推导歧义:原
CustomException的构造函数模板未明确区分fmt格式字符串参数,导致GMock的Throw转发参数时,编译器无法正确推导fmt的格式字符串类型。
修正后的代码
#include <gtest/gtest.h> #include <gmock/gmock.h> #include <stdexcept> #include <fmt/core.h> using ::testing::_; using ::testing::Throw; class CustomException : public std::exception { public: // 显式声明格式字符串类型,消除模板推导歧义 template <typename... Args> explicit CustomException(fmt::format_string<Args...> fmt, Args&&... args) : _exception_string{fmt::format(fmt, std::forward<Args>(args)...) + _exception_suffix} { } inline const char* what() const noexcept override { return _exception_string.c_str(); } private: std::string _exception_suffix{" Custom exception..."}; std::string _exception_string{}; }; class Calculator { public: virtual double Divide(double a, double b) { if (b == 0.0) { throw std::invalid_argument("Division by zero"); } return a / b; } }; // Mock class for Calculator class MockCalculator : public Calculator { public: MOCK_METHOD(double, Divide, (double a, double b), (override)); }; TEST(CalculatorTest, DivideWithExceptions) { MockCalculator mockCalculator; EXPECT_CALL(mockCalculator, Divide(10.0, 0.0)) .WillOnce(Throw(CustomException("Division by zero"))); try { double result = mockCalculator.Divide(10.0, 0.0); FAIL() << "Expected exception not thrown."; } catch (const CustomException& e) { EXPECT_STREQ(e.what(), "Division by zero Custom exception..."); } catch (...) { FAIL() << "Caught unexpected exception type."; } } int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
关键修改点
- 构造函数优化:将第一个参数显式指定为
fmt::format_string<Args...>,明确告知编译器该参数为fmt格式字符串,解决模板推导的类型歧义问题。 - 捕获类型修正:把catch块的捕获类型改为
const CustomException&,确保能正确捕获自定义异常,同时添加兜底捕获块处理意外情况。 - 验证逻辑更新:调整
EXPECT_STREQ的预期值,匹配自定义异常拼接后的完整错误信息。
内容的提问来源于stack exchange,提问作者pankaj kushwaha
相关产品推荐
相关产品推荐

