使用GoMock包进行单元测试的最佳实践
使用GoMock包进行单元测试的最佳实践
需求:
在模拟一个函数时,传入了一个空参数,该参数应在函数内部被填充。
使用 gomock.Matcher 可以通过强制赋值实现,但使用 gomock.AssignableToTypeOf 会失败。
需要在不使用匹配器的情况下实现此功能。
示例:
func main() {
fmt.Println("hello world")
}
1 回复
在GoMock中处理函数内部填充参数的情况,可以通过Do和SetArg方法实现。以下是具体实现方案:
package main
import (
"testing"
"github.com/golang/mock/gomock"
)
// 定义接口
type DataProcessor interface {
Process(data *InputData) error
}
type InputData struct {
ID string
Name string
}
// 测试示例
func TestProcessData(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockProcessor := NewMockDataProcessor(ctrl)
// 创建空参数
input := &InputData{}
// 使用Do函数在调用时填充参数
mockProcessor.EXPECT().
Process(gomock.Any()).
Do(func(arg *InputData) {
// 在调用时填充参数
arg.ID = "123"
arg.Name = "test"
}).
Return(nil)
// 执行测试
err := mockProcessor.Process(input)
if err != nil {
t.Fatalf("Process failed: %v", err)
}
// 验证参数已被填充
if input.ID != "123" || input.Name != "test" {
t.Errorf("Expected ID=123, Name=test, got ID=%s, Name=%s", input.ID, input.Name)
}
}
对于需要修改特定位置参数的情况,可以使用SetArg:
func TestProcessWithSetArg(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockProcessor := NewMockDataProcessor(ctrl)
input := &InputData{}
mockProcessor.EXPECT().
Process(gomock.Any()).
SetArg(0, InputData{ID: "456", Name: "example"}).
Return(nil)
err := mockProcessor.Process(input)
if err != nil {
t.Fatalf("Process failed: %v", err)
}
if input.ID != "456" || input.Name != "example" {
t.Errorf("Expected ID=456, Name=example, got ID=%s, Name=%s", input.ID, input.Name)
}
}
对于需要更复杂逻辑的情况,可以结合使用Do和类型断言:
func TestProcessWithComplexLogic(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockProcessor := NewMockDataProcessor(ctrl)
input := &InputData{}
mockProcessor.EXPECT().
Process(gomock.Any()).
Do(func(arg interface{}) {
if data, ok := arg.(*InputData); ok {
data.ID = "789"
data.Name = "complex"
// 可以添加更多业务逻辑
}
}).
Return(nil)
err := mockProcessor.Process(input)
if err != nil {
t.Fatalf("Process failed: %v", err)
}
if input.ID != "789" || input.Name != "complex" {
t.Errorf("Expected ID=789, Name=complex, got ID=%s, Name=%s", input.ID, input.Name)
}
}
这些方法避免了使用gomock.Matcher或gomock.AssignableToTypeOf,直接在模拟调用时修改传入的参数值。Do方法适用于需要执行自定义逻辑的情况,而SetArg方法适用于直接替换参数值的简单场景。

