当前位置:网站首页>Use gomonkey mock function and method

Use gomonkey mock function and method

2022-06-22 01:30:00 CG Guobin

Preface

stay Golang In language , When writing unit tests , Inevitably, it will involve the modification of other functions and methods Mock, That is, while assuming that other functions and methods respond to the expected results , Verify whether the response of the function under test meets the expectation .

among , stay Mock Other functions and methods , A common test class library we use is 「gomonkey」. Specially , For methods and functions Mock, Slightly different , Here we give functions and methods respectively Mock Example , For your reference .

function

stay Golang In language , A function is a method that has no receiver , In the form of

func function_name([parameter list]) [return_types] {
    
    The body of the function 
}

For function Mock Relatively simple , Suppose we are right A Function to unit test , And A Function called again B function , for example

func A(ctx context.Context, str string) error {
    
   if len(str) == 0 {
    
	  return errors.New("str is empty")
   }
   return test_package_name.B(ctx, str)
}

In order to A Each line of the function covers , The unit test can be written as :

func TestA(t *testing.T) {
    
	type args struct {
    
		ctx    context.Context
		str    string
	}
	tests := []struct {
    
		name    string
		args    args
		Setup   func(t *testing.T)
		wantErr error
	}{
    
		{
    
			name: "len(str) == 0",
			wantErr: errors.New("str is empty")
		},
		{
    
			name: " Normal response ",
			Setup: func(t *testing.T) {
    
				patches := gomonkey.ApplyFunc(test_package_name.B, func(_ context.Context, _ string) error {
    
					return nil
				})
				t.Cleanup(func() {
    
					patches.Reset()
				})
			},
			args: args{
    
				ctx:     context.Background(),
				str:     "test",
			},
			wantErr: nil,
		},
	}

	//  Execute test case 
	for _, tt := range tests {
    
		t.Run(tt.name, func(t *testing.T) {
    
			if tt.Setup != nil {
    
				tt.Setup(t)
			}
			err := A(tt.args.ctx, tt.args.str)
			if err != nil {
    
				assert.EqualError(t, err, tt.wantErr.Error(), "error  Fall short of expectations ")
			}
		})
	}
}

among ,ApplyFunc The function is used to Mock Functional , The first parameter is required Mock The function name of ( There is no need to write parameter list ), The second parameter is required Mock Function result of ; Specially , stay Setup Inside , We need to remember to explicitly call Cleanup Yes patches Conduct Reset operation , Prevent the Mock Affect other test cases .

Method

stay Golang In language , The method is a function that contains the receiver , In the form of

func (variable_name variable_data_type) function_name([parameter list]) [return_type]{
    
    The body of the function 
}

For method Mock It's relatively complicated , Suppose we are right A Function to unit test , And A The structure is called in the function C Of B Method , for example

func A(ctx context.Context, str string) error {
    
   if len(str) == 0 {
    
	  return errors.New("str is empty")
   }
   c := &test_package_name.C{
    }
   return c.B(ctx, str)
}

In order to A Each line of the function covers , The unit test can be written as :

func TestA(t *testing.T) {
    
	//  initialization C structure 
	var c *test_package_name.C
	
	type args struct {
    
		ctx    context.Context
		str    string
	}
	tests := []struct {
    
		name    string
		args    args
		Setup   func(t *testing.T)
		wantErr error
	}{
    
		{
    
			name: "len(str) == 0",
			wantErr: errors.New("str is empty")
		},
		{
    
			name: " Normal response ",
			Setup: func(t *testing.T) {
    
				patches := gomonkey.ApplyMethod(reflect.TypeOf(c), "B", func(_ *test_package_name.C, _ context.Context, _ string) error {
    
					return nil
				})
				t.Cleanup(func() {
    
					patches.Reset()
				})
			},
			args: args{
    
				ctx:     context.Background(),
				str:     "test",
			},
			wantErr: nil,
		},
	}

	//  Execute test case 
	for _, tt := range tests {
    
		t.Run(tt.name, func(t *testing.T) {
    
			if tt.Setup != nil {
    
				tt.Setup(t)
			}
			err := A(tt.args.ctx, tt.args.str)
			if err != nil {
    
				assert.EqualError(t, err, tt.wantErr.Error(), "error  Fall short of expectations ")
			}
		})
	}
}

among ,ApplyMethod The function is used to Mock Methodical , The first parameter is required Mock The recipient type of the method of , The second parameter is required Mock Method name of ( String type ), The third parameter is required Mock The definition and Mock result ; Specially , The first and third parameters require our attention :

  • The first parameter , Need to use reflect.TypeOf Get the type of recipient , The initialized recipient must be a real type , Such as structure C Combined structure D, and B The method is to combine D Got , You need to define the structure during initialization D, Not the structure C, Otherwise, null pointer exception will be reported ;
  • The third parameter , although B The method declaration is func(ctx context.Context, str string), But in use ApplyMethod When , Need to put B The declaration of the method is modified to func(c *test_package_name.C, ctx context.Context, str string), That is, you need to set the receiver of the method as the first parameter of the method .

Reference resources

And that is , We are using gomonkey When , You may encounter the problem of permission verification and non - Debug The problem that the mode fails to run , You can refer to :

Come here , This is the end of the article , I hope that's helpful .

原网站

版权声明
本文为[CG Guobin]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/173/202206220034157439.html