Golang表格驱动测试中如何为不同子测试设置不同Mock?
解决Go表格驱动测试中Mock变量的隔离问题
你当前的测试代码里,mockStr定义在Test_funcTest的函数作用域内,属于所有子测试共享的变量,test1修改它后会影响test2的执行,导致测试相互污染。以下是几种可行的解决方法:
方法1:给测试用例结构体添加专属Mock字段
把每个测试用例需要的mockStr值加到测试结构体中,在子测试执行前单独设置这个变量,确保每个子测试使用自己的Mock值。
func Test_funcTest(t *testing.T) { type args struct { arg1 string arg2 string } // 测试结构体新增mockStr字段,存储当前用例的专属Mock值 tests := []struct { name string args args want string wantErr bool mockStr string }{ { name: "test1", args: args{arg1: "arg1", arg2: "arg2"}, want: "res1", wantErr: false, mockStr: "mock1", // test1的专属Mock值 }, { name: "test2", args: args{arg1: "arg1", arg2: "arg2"}, want: "res2", wantErr: false, mockStr: "mock2", // test2的专属Mock值 }, } for _, tt := range tests { tt := tt // 捕获循环变量,避免闭包引用问题 t.Run(tt.name, func(t *testing.T) { // 子测试中设置当前用例的Mock值 mockStr = tt.mockStr got, err := funcTest(tt.args.arg1, tt.args.arg2) if (err != nil) != tt.wantErr { t.Errorf("funcTest() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { t.Errorf("funcTest() = %v, want %v", got, tt.want) } }) } }
方法2:使用t.Cleanup()恢复原始值
如果mockStr是全局变量或无法直接嵌入测试结构体,可以在子测试修改前保存原始值,通过t.Cleanup()在测试结束后恢复,确保每个子测试的修改不会污染其他测试。
func Test_funcTest(t *testing.T) { type args struct { arg1 string arg2 string } tests := []struct { name string args args want string wantErr bool mockStr string }{ { name: "test1", args: args{arg1: "arg1", arg2: "arg2"}, want: "res1", wantErr: false, mockStr: "mock1", }, { name: "test2", args: args{arg1: "arg1", arg2: "arg2"}, want: "res2", wantErr: false, mockStr: "mock2", }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { // 保存当前mockStr的原始值 prevMock := mockStr // 测试结束后自动恢复原始值 t.Cleanup(func() { mockStr = prevMock }) // 设置当前测试的Mock值 mockStr = tt.mockStr got, err := funcTest(tt.args.arg1, tt.args.arg2) if (err != nil) != tt.wantErr { t.Errorf("funcTest() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { t.Errorf("funcTest() = %v, want %v", got, tt.want) } }) } }
方法3:重构代码使用依赖注入(推荐)
这是最彻底的解决方案,让funcTest不依赖外部的mockStr变量,而是通过参数传入需要的字符串,从根源上避免测试污染问题。
重构后的funcTest:
func funcTest(arg1, arg2, mockStr string) (string, error) { // 原逻辑改为使用传入的mockStr参数 // ... }
对应的测试代码:
func Test_funcTest(t *testing.T) { type args struct { arg1 string arg2 string mockStr string // 将mockStr作为测试参数传入 } tests := []struct { name string args args want string wantErr bool }{ { name: "test1", args: args{ arg1: "arg1", arg2: "arg2", mockStr: "mock1", }, want: "res1", wantErr: false, }, { name: "test2", args: args{ arg1: "arg1", arg2: "arg2", mockStr: "mock2", }, want: "res2", wantErr: false, }, } for _, tt := range tests { tt := tt t.Run(tt.name, func(t *testing.T) { got, err := funcTest(tt.args.arg1, tt.args.arg2, tt.args.mockStr) if (err != nil) != tt.wantErr { t.Errorf("funcTest() error = %v, wantErr %v", err, tt.wantErr) return } if got != tt.want { t.Errorf("funcTest() = %v, want %v", got, tt.want) } }) } }
内容的提问来源于stack exchange,提问作者Mihika
相关产品推荐
相关产品推荐

