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

如何用mock-turtle mock外部库函数解决链接错误?

解决mock-turtle模拟外部库函数的链接错误问题

针对你遇到的undefined reference to 'send_conf'链接错误,本质是测试编译时未链接libdevice库,且A.cpp直接硬编码调用了该库函数。下面给你几个实用的解决思路:


方案一:用编译宏切换实际调用与Mock函数

这种方式无需大幅修改现有代码,通过预编译宏控制A.cpp调用的是实际库函数还是Mock函数:

  1. 修正并修改A.cpp,添加宏判断:
#include <libdevice.h>

class A{
public:
    bool connect() {
        int myconf = 3;
#ifdef TEST_MODE
        // 测试模式下调用mock的send_conf
        extern "C" int send_conf(int);
#endif
        if(send_conf(myconf) == -1) {
            return false;
        }
        return true;
    }
};

(注:原代码中public class A是C++语法错误,已修正为标准类定义)

  1. 编译测试代码时添加宏定义:
    例如使用g++编译时,加上-DTEST_MODE参数,让A.cpp编译为调用mock版本的send_conf,无需链接libdevice库。

  2. 测试代码保持原有Mock定义:
    test_A.cpp中的MOCK_FUNCTION定义不变,编译测试时链接mock-turtle与Boost.Test库即可。


方案二:封装外部依赖为接口(更优雅的解耦方式)

若希望代码结构更灵活、易维护,可将外部库函数封装为抽象接口,让A类依赖接口而非直接调用库函数:

  1. 定义抽象接口类:
    新建DeviceController.h文件:
class DeviceController {
public:
    virtual ~DeviceController() = default;
    virtual int send_conf(int conf) = 0;
};
  1. 实现生产环境的控制器:
    新建RealDeviceController.cpp:
#include "DeviceController.h"
#include <libdevice.h>

class RealDeviceController : public DeviceController {
public:
    int send_conf(int conf) override {
        return ::send_conf(conf); // 调用实际库的send_conf
    }
};
  1. 修改A类,依赖接口:
    修改A.cpp:
#include "DeviceController.h"

class A{
private:
    DeviceController* controller;
public:
    // 构造时注入控制器,生产环境传RealDeviceController,测试传mock
    A(DeviceController* ctrl) : controller(ctrl) {}

    bool connect() {
        int myconf = 3;
        if(controller->send_conf(myconf) == -1) {
            return false;
        }
        return true;
    }
};
  1. 测试时Mock接口类:
    用mock-turtle模拟DeviceController接口,修改test_A.cpp:
#include "DeviceController.h"
#include "A.h"
#include <mockturtle/mockturtle.hpp>
#include <boost/test/unit_test.hpp>

using namespace mockturtle;

BOOST_AUTO_TEST_CASE(connect_test) {
    // 创建mock的DeviceController
    mock<DeviceController> mock_ctrl;
    MOCK_EXPECT(mock_ctrl.send_conf).once().with(3).returns(-1);

    // 注入mock对象到A类
    A myA(mock_ctrl.get());
    bool ret = myA.connect();

    BOOST_CHECK_EQUAL(ret, false); 
}

这种方式彻底解耦了A类与外部库的依赖,测试时无需关心libdevice的存在,更符合面向接口编程思想。


方案三:利用链接优先级覆盖符号(快速临时方案)

若不想修改太多代码,可利用链接器的符号优先级,让mock的send_conf先被链接,覆盖实际库的符号:

  1. 确保Mock函数为C语言导出:
    你的test_A.cpp已用extern "C"包裹MOCK_FUNCTION,这一步没问题(libdevice的send_conf应为C语言导出)。

  2. 调整编译链接顺序:
    编译时先链接test_A.o再链接A.o,例如:

g++ -c A.cpp -o A.o
g++ -c test_A.cpp -o test_A.o -I/path/to/mockturtle -I/path/to/boost
g++ test_A.o A.o -o test_A -lboost_unit_test_framework -lmockturtle

链接器会优先从test_A.o找到send_conf符号,不会再去libdevice中查找。但这种方式依赖链接顺序,稳定性较差,适合临时测试场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 23:36:21