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

如何通过D-Bus对等连接Mock ModemManager测试Go语言WWAN配置程序?

基于D-Bus对等连接Mock ModemManager的Go测试实现

1. 初始化D-Bus对等连接

通过创建双向管道搭建客户端(你的应用代码)与Mock服务器的直接通信,无需依赖系统D-Bus总线。用net.Pipe()生成双向管道,再通过godbus的NewConn初始化两端连接:

// 创建双向管道
clientConn, serverConn := net.Pipe()

// 初始化客户端D-Bus连接
dbusClient, err := dbus.NewConn(clientConn)
if err != nil {
    t.Fatal(err)
}
defer dbusClient.Close()

// 初始化服务器端D-Bus连接
dbusServer, err := dbus.NewConn(serverConn)
if err != nil {
    t.Fatal(err)
}
defer dbusServer.Close()

2. 实现Mock ModemManager服务

2.1 注册ModemManager服务名

在服务器端申请org.freedesktop.ModemManager1服务名,确保成为主所有者:

reply, err := dbusServer.RequestName("org.freedesktop.ModemManager1", dbus.NameFlagDoNotQueue)
if err != nil {
    t.Fatal(err)
}
if reply != dbus.RequestNameReplyPrimaryOwner {
    t.Fatal("无法获取ModemManager服务名所有权")
}

2.2 定义Mock对象与接口

根据ModemManager的D-Bus规范,创建结构体模拟核心接口的行为,比如模拟Simple.Connect和EnumerateModems方法:

// 模拟ModemManager主接口
type MockModemManager struct {
    t *testing.T
}

func (m *MockModemManager) EnumerateModems() ([]dbus.ObjectPath, *dbus.Error) {
    return []dbus.ObjectPath{"/org/freedesktop/ModemManager1/Modem/0"}, nil
}

// 模拟Modem的Simple接口
type MockModemSimple struct {
    t *testing.T
}

func (m *MockModemSimple) Connect(settings map[string]interface{}) (dbus.ObjectPath, *dbus.Error) {
    // 验证应用传入的配置参数
    if apn, ok := settings["apn"]; !ok || apn != "test-apn" {
        m.t.Error("APN参数不符合预期")
    }
    // 返回模拟的Bearer对象路径
    return dbus.ObjectPath("/org/freedesktop/ModemManager1/Bearer/0"), nil
}

将Mock结构体注册到对应对象路径:

// 注册主服务对象与接口
err = dbusServer.Export(&MockModemManager{t: t}, "/org/freedesktop/ModemManager1", "org.freedesktop.ModemManager1")
if err != nil {
    t.Fatal(err)
}

// 注册Modem对象与Simple接口
err = dbusServer.Export(&MockModemSimple{t: t}, "/org/freedesktop/ModemManager1/Modem/0", "org.freedesktop.ModemManager1.Modem.Simple")
if err != nil {
    t.Fatal(err)
}

3. 测试应用的WWAN配置逻辑

修改应用代码,支持传入自定义D-Bus连接(而非默认的系统总线),然后在测试用例中传入对等连接:

// 应用中的WWAN配置函数,支持自定义D-Bus连接
func ConfigureWWAN(conn *dbus.Conn, apn string) error {
    mmObj := conn.Object("org.freedesktop.ModemManager1", "/org/freedesktop/ModemManager1")
    
    // 枚举Modem
    var modems []dbus.ObjectPath
    err := mmObj.Call("org.freedesktop.ModemManager1.EnumerateModems", 0).Store(&modems)
    if err != nil {
        return err
    }
    if len(modems) == 0 {
        return fmt.Errorf("未找到Modem设备")
    }
    
    // 调用Simple.Connect接口
    modemSimple := conn.Object("org.freedesktop.ModemManager1", modems[0])
    _, err = modemSimple.Call("org.freedesktop.ModemManager1.Modem.Simple.Connect", 0, map[string]interface{}{
        "apn": apn,
    })
    return err
}

// 测试用例
func TestConfigureWWAN(t *testing.T) {
    // 初始化对等连接的代码...
    
    err := ConfigureWWAN(dbusClient, "test-apn")
    if err != nil {
        t.Fatal(err)
    }
}

4. 模拟D-Bus信号(可选)

如果应用依赖ModemManager的信号(如ModemAdded),可在Mock服务器中主动发送信号:

// 发送ModemAdded信号
err = dbusServer.Emit("/org/freedesktop/ModemManager1", "org.freedesktop.ModemManager1.ModemAdded", dbus.ObjectPath("/org/freedesktop/ModemManager1/Modem/0"))
if err != nil {
    t.Fatal(err)
}

客户端需提前注册信号处理器,与生产环境逻辑一致即可。

注意事项

  • 严格匹配ModemManager的D-Bus接口签名(参数、返回值类型),避免调用失败;
  • 可在Mock方法中加入断言,验证应用传入的参数是否符合预期;
  • 参考ModemManager官方D-Bus文档确认接口、信号的定义细节。

内容的提问来源于stack exchange,提问作者Kamil Zaripov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 18:15:59