Golang单元测试Mock Netconf会话:解决Close()空指针问题
解决Juniper go-netconf会话Mock时Close()空指针panic问题
你遇到的空指针panic,是因为Mock的netconf.Session仅初始化了SessionID字段,但结构体内部未导出的底层连接字段(如conn)为nil,调用Close()方法时会尝试操作这个空指针,导致panic。
方案一:通过接口抽象解耦(推荐)
这种方法遵循依赖倒置原则,将具体的netconf.Session替换为接口,彻底解耦业务代码与第三方包,Mock更灵活:
- 定义业务所需的Netconf会话接口
只包含你的代码实际用到的方法,比如Close()和RPC发送方法:
type NetconfSession interface { Close() error SendRPC(rpc string) (*netconf.RPCReply, error) // 按需添加其他你需要调用的方法 }
- 修改连接获取函数的返回类型
将getSSHConnection的返回类型改为上述接口:
var getSSHConnection func() (NetconfSession, error)
- 编写Mock会话结构体
实现NetconfSession接口,Close()方法做空实现(或根据测试需求添加断言逻辑):
type MockNetconfSession struct { SessionID int MockRPCReply *netconf.RPCReply // 可自定义字段模拟RPC返回 MockRPCErr error } func (m *MockNetconfSession) Close() error { // 空实现,避免空指针panic return nil } func (m *MockNetconfSession) SendRPC(rpc string) (*netconf.RPCReply, error) { // 返回预设的模拟结果 return m.MockRPCReply, m.MockRPCErr }
- 更新Mock连接函数
返回Mock会话实例:
func mockGetSSHConnection() (NetconfSession, error) { return &MockNetconfSession{SessionID: 123}, nil }
这样业务代码中调用sess.Close()时,会执行Mock的空实现,不会触发空指针问题,同时还能灵活模拟RPC的返回结果。
方案二:反射初始化未导出字段(不推荐)
如果不想修改现有接口结构,可以通过反射给netconf.Session的未导出连接字段赋值一个非nil的模拟连接,但这种方法依赖第三方包的内部实现,后续包版本更新可能失效:
import ( "io" "net" "reflect" "time" "github.com/Juniper/go-netconf/netconf" ) func mockGetSSHConnection() (*netconf.Session, error) { sess := &netconf.Session{SessionID: 123} // 用反射找到并设置内部的conn字段 connField := reflect.ValueOf(sess).Elem().FieldByName("conn") if connField.IsValid() && connField.CanSet() { // 创建一个模拟的net.Conn实现 r, w := io.Pipe() mockConn := &mockNetConn{Reader: r, Writer: w} connField.Set(reflect.ValueOf(mockConn)) } return sess, nil } // mockNetConn 实现net.Conn接口 type mockNetConn struct { io.Reader io.Writer } func (m *mockNetConn) Close() error { return nil } func (m *mockNetConn) LocalAddr() net.Addr { return nil } func (m *mockNetConn) RemoteAddr() net.Addr { return nil } func (m *mockNetConn) SetDeadline(t time.Time) error { return nil } func (m *mockNetConn) SetReadDeadline(t time.Time) error { return nil } func (m *mockNetConn) SetWriteDeadline(t time.Time) error { return nil }
内容的提问来源于stack exchange,提问作者Niranjan Raghu
相关产品推荐
相关产品推荐

