You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何Mock对boost::posix_time::microsec_clock::local_time()的调用?

解决方案

首先明确之前直接Mock函数不生效的核心原因:代码中硬编码了对pt::microsec_clock::local_time()的直接调用,该函数是boost库的静态成员函数,默认编译场景下可能被内联优化,Mock框架无法拦截无虚函数接口的静态/全局函数调用。

方案1:依赖注入改造(最稳定,推荐使用)

通过抽象时间获取接口,将时间获取逻辑从业务代码中解耦,实现可Mock性,改造对原有生产逻辑无侵入。

步骤1:定义时间提供者抽象接口

#include <boost/date_time/posix_time/posix_time.hpp>
namespace pt = boost::posix_time;

class TimeProvider {
public:
    virtual ~TimeProvider() = default;
    virtual pt::ptime getCurrentLocalTime() const = 0;
};

步骤2:实现生产环境用的真实时间提供者

class RealTimeProvider : public TimeProvider {
public:
    pt::ptime getCurrentLocalTime() const override {
        return pt::microsec_clock::local_time();
    }
};

步骤3:修改OEManager类,注入时间提供者

给OEManager增加TimeProvider类型的成员,构造函数默认注入真实时间提供者,不影响原有生产逻辑:

class OEManager {
private:
    std::unique_ptr<TimeProvider> time_provider_;
    int sequence_id = 0; // 原有成员
public:
    // 构造函数默认使用真实时间提供者,生产环境无感知
    explicit OEManager(std::unique_ptr<TimeProvider> provider = std::make_unique<RealTimeProvider>())
        : time_provider_(std::move(provider)) {}
    
    std::string generateActionCommand(const char* cmd_type);
    // 其他原有方法
};

步骤4:修改generateActionCommand的时间获取逻辑

将原来直接调用boost接口的代码替换为调用注入的时间提供者接口:

std::string OEManager::generateActionCommand(const char* cmd_type) {
    std::string ret_msg;
    // 替换原有硬编码的boost调用
    pt::ptime current_time = time_provider_->getCurrentLocalTime();
    char timestamp[13];
    snprintf(timestamp, 13, "%02d:%02d:%02d.%03d", 
                    current_time.time_of_day().hours(), current_time.time_of_day().minutes(), 
                    current_time.time_of_day().seconds(), 
                    // 微秒转毫秒,适配格式化逻辑
                    current_time.time_of_day().fractional_seconds() / 1000);
    ret_msg = timestamp;
    ret_msg.append ("," + std::to_string(sequence_id) + "," + cmd_type);
    return ret_msg;
}

步骤5:编写Mock类和测试用例

用turtle-mock定义Mock时间提供者,即可自定义返回指定时间点,精确校验生成的字符串:

#include <turtle/mock.hpp>
// 定义Mock类
MOCK_BASE_CLASS(MockTimeProvider, TimeProvider)
{
    MOCK_CONST_METHOD(getCurrentLocalTime, 0, pt::ptime());
};

// 测试用例示例
BOOST_AUTO_TEST_CASE(test_generateActionCommand_timestamp_correct)
{
    // 构造预期时间:2024-05-20 13:14:15.123
    pt::ptime test_time(pt::date(2024,5,20), pt::time_duration(13,14,15, 123000));
    auto mock_provider = std::make_unique<MockTimeProvider>();
    // 设置mock返回指定时间
    MOCK_EXPECT(mock_provider->getCurrentLocalTime).returns(test_time);

    // 注入mock对象构造OEManager
    OEManager manager(std::move(mock_provider));
    // 假设sequence_id为1001,根据实际实现赋值
    std::string result = manager.generateActionCommand("START");

    // 直接精确比对结果,不需要正则校验
    BOOST_CHECK_EQUAL(result, "13:14:15.123,1001,START");
}

方案2:链接期全局Mock(不推荐)

如果不想修改原有类结构,可以尝试全局Mock,但存在编译优化导致拦截失效的风险:

  1. 确保编译时关闭boost相关函数的内联优化,添加编译参数-fno-inline等(不同平台参数不同)
  2. 正确指定命名空间,用turtle的MOCK_FUNCTION定义mock:
MOCK_FUNCTION(pt::microsec_clock, local_time, 0, pt::ptime());
  1. 测试用例中设置该函数的返回值即可,但是这种方案在不同编译器、不同编译配置下稳定性很差,不建议生产测试使用。

内容的提问来源于stack exchange,提问作者Gionata Benelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 00:54:06