如何在 Golang 的单元测试中模拟 Netconf 会话?

huangapple go评论93阅读模式
英文:

How do I mock netconf session in unit tests Golang

问题

我正在使用Juniper的netconf包("github.com/Juniper/go-netconf/netconf")在我的代码中建立netconf会话。

我想知道如何在我的单元测试中模拟netconf会话。

我的方法是:

func TestMyFunction(t *testing.T) {
    getSSHConnection = mockGetSSHConnection
    got := MyFunction()
    want := 123
    if !reflect.DeepEqual(got, want) {
        t.Errorf("Error expectation not met, want %v, got %v", want, got)
    }
}
func mockGetSSHConnection() (*netconf.Session, error) {
    var sess netconf.Session
    sess.SessionID = 123
    return &sess, nil
}

问题出现在MyFunction()中有一行代码defer sess.Close(),由于空指针解引用而引发错误。

func MyFunction() int {
    sess, err := getSSHConnection() // 返回 (*netconf.Session, error)
    if err == nil && sess != nil {
        defer sess.Close() -> 问题发生在这里
        // 在这里调用RPC和其他代码
        
    } 
    return 0
}

那么,我应该如何修改mockGetSSHConnection()方法,以便sess.Close()不会引发错误?

英文:

I am using juniper's netconf package ("github.com/Juniper/go-netconf/netconf") to establish a netconf session in my code.

I wanted to know how can I mock a netconf session in my unit tests.

My methods are:

func TestMyFunction(t *testing.T) {
	getSSHConnection = mockGetSSHConnection
	got := MyFunction()
	want := 123
	if !reflect.DeepEqual(got, want) {
		t.Errorf("Error expectation not met, want %v, got %v", want, got)
	}
}
func mockGetSSHConnection() (*netconf.Session, error) {
	var sess netconf.Session
	sess.SessionID = 123
	return &sess, nil
}

The problem arises when MyFunction() has a line that defers sess.Close() and it's throwing error due to nil pointer dereference

func MyFunction() int {
	sess, err := getSSHConnection() // returns (*netconf.Session, error)
	if err == nil && sess != nil {
		defer sess.Close() -> Problem happens here
		// Calls RPC here and rest of the code here
		
	} 
	return 0
}

So, what changes can I make on mockGetSSHConnection() method so that sess.Close() won't throw error?

答案1

得分: 3

nil指针错误是在Close函数中发生的,当在底层的Transport上调用Close时会出现该错误。幸运的是,Transport是一个接口类型,你可以轻松地模拟并在netconf.Session的实例中使用。例如:

type MockTransport struct{}

func (t *MockTransport) Send([]byte) error {
    return nil
}

func (t *MockTransport) Receive() ([]byte, error) {
    return []byte{}, nil
}

func (t *MockTransport) Close() error {
    return nil
}

func (t *MockTransport) ReceiveHello() (*netconf.HelloMessage, error) {
    return &netconf.HelloMessage{SessionID: 123}, nil
}

func (t *MockTransport) SendHello(*netconf.HelloMessage) error {
    return nil
}

func (t *MockTransport) SetVersion(version string) {
}

func mockGetSSHConnection() (*netconf.Session, error) {
    t := MockTransport{}
    sess := netconf.NewSession(&t)
    return sess, nil
}

请注意,你想要测试的函数当前返回的是0而不是会话的SessionID。所以在测试成功之前,你应该修复这个问题。

英文:

The nil pointer error originates within the Close function when Close is called on the underlying Transport. Fortunately Transport is an interface type that you can easily mock and use in an actual instance of the netconf.Session. For example like so:

type MockTransport struct{}

func (t *MockTransport) Send([]byte) error {
	return nil
}

func (t *MockTransport) Receive() ([]byte, error) {
	return []byte{}, nil
}

func (t *MockTransport) Close() error {
	return nil
}

func (t *MockTransport) ReceiveHello() (*netconf.HelloMessage, error) {
	return &netconf.HelloMessage{SessionID: 123}, nil
}

func (t *MockTransport) SendHello(*netconf.HelloMessage) error {
	return nil
}

func (t *MockTransport) SetVersion(version string) {
}

func mockGetSSHConnection() (*netconf.Session, error) {
	t := MockTransport{}
	sess := netconf.NewSession(&t)
	return sess, nil
}

Note that the function you want to test currently return 0 and not the SessionID of the session. So you should fix that before the test is successful.

答案2

得分: 0

你可以使用面向对象编程(OOP)和"github.com/stretchr/testify/mock"包。

例如,创建以下结构体:

type SshClientMock struct {
    mock.Mock
}

func (s *SshClientMock) GetSSHConnection() {
    return //你需要什么
}

在你的单元测试中:

sshClient := SshClientMock{}
sshClient.On("GetSSHConnection").Return(你需要什么)

然后调用你的方法
英文:

You could use OOP and "github.com/stretchr/testify/mock" package

for example create

type SshClientMock struct {
    mock.Mock
}

func (s *SshClientMock) GetSSHConnection() {
    return //what do you need
}

in your unit test:

sshClient := SshClientMock
sshClient.On("GetSSHConnection").Return(what do you need)

and then call your method

huangapple
  • 本文由 发表于 2022年12月16日 14:50:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/74821046.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定