在GoogleTest中结合ASSERT_DEATH添加调用预期的问题排查
问题分析
你遇到的问题有两个核心原因:
- Mock指针失效:Fixture的
SetUp方法中通过std::move将m_mock_temperature的所有权转移给了SUT,导致测试用例中的m_mock_temperature变为空指针,后续EXPECT_CALL绑定的是无效对象,无法捕获SUT内部Mock的调用行为。 - 死亡测试的进程隔离:
ASSERT_DEATH通过fork子进程执行被测代码,子进程内的Mock调用不会同步到父进程,父进程的EXPECT_CALL无法检测到子进程中的调用记录,因此会误报"get_temp从未被调用"。
解决方案
步骤1:调整Fixture结构,保存Mock裸指针
修改Fixture,在将Mock转移给SUT前保存裸指针,确保测试用例能正确访问SUT内部的Mock对象:
class Fixture : public testing::Test { protected: void SetUp() override { // 创建温度Mock并保存裸指针 auto temp_mock = std::make_unique<StrictMock<MockITemperature>>(); m_temp_mock_ptr = temp_mock.get(); // 湿度Mock设为nullptr,触发目标assert m_sut = std::make_unique<SoftwareUnderTest>(std::move(temp_mock), nullptr); } StrictMock<MockITemperature>* m_temp_mock_ptr = nullptr; std::unique_ptr<SoftwareUnderTest> m_sut; };
步骤2:使用ASSERT_EXIT替代ASSERT_DEATH,在子进程内完成验证
ASSERT_EXIT允许在子进程中执行代码并同时验证Mock调用和进程退出行为。在子进程内设置Mock期望,确保get_temp被调用且返回值≥50(触发湿度检查的assert分支):
TEST_F(Fixture, GIVEN_AnInvalidHumidityInjection_THEN_TestMustDie) { ASSERT_EXIT( { // 在子进程内设置Mock期望:get_temp被调用1次,返回60(≥50) EXPECT_CALL(*m_temp_mock_ptr, get_temp) .Times(1) .WillOnce(testing::Return(60)); // 执行被测方法 m_sut->checker(); // 如果未触发assert,主动退出并标记测试失败 std::exit(EXIT_FAILURE); }, // 验证进程被SIGABRT信号终止(assert触发的标准信号) testing::KilledBySignal(SIGABRT), // 验证错误输出包含目标提示字符串 "No humidity"); }
方案解释
- 裸指针保存:避免了
std::move后智能指针为空的问题,确保测试用例能正确关联SUT内部的Mock对象。 - 子进程内验证:
ASSERT_EXIT的代码块在子进程中执行,Mock期望的验证和被测方法的调用在同一进程内完成,确保get_temp的调用能被正确检测。如果get_temp未被调用,子进程内的EXPECT_CALL会触发失败,导致子进程异常退出,ASSERT_EXIT会捕获到这个错误,测试直接失败。同时,我们验证了进程是被SIGABRT终止且输出包含"No humidity",确保触发了目标assert。
内容的提问来源于stack exchange,提问作者josecgon
相关产品推荐
相关产品推荐

