Golang单元测试:验证传递给Mock的FileFilter参数正确性
问题解答
可以校验ReadAllBy方法传入的filters是否正确,当前测试不生效是因为mock.AnythingOfType("FileFilter")仅校验参数类型,不校验函数的具体逻辑或绑定的目标参数。下面给出两种可行方案:
方案一:校验Filter的行为(推荐)
FileFilter是函数类型,核心要验证的是它的行为是否符合ByExtension("log")的预期。可以在Mock断言中自定义匹配器,调用传入的Filter并验证执行结果:
import ( "github.com/stretchr/testify/mock" "your/models/package/path" ) // 自定义匹配器,验证Filter是ByExtension("log")生成的实例 func isLogFilter() mock.Matcher { return mock.MatchedBy(func(filter FileFilter) bool { // 创建测试用File实例,验证Filter的逻辑 testLogFile := &models.File{Extension: "log"} testTxtFile := &models.File{Extension: "txt"} // 匹配正确扩展名返回true、错误扩展名返回false的行为 return filter(testLogFile) == true && filter(testTxtFile) == false }) } // 测试代码 func TestService(t *testing.T) { // 初始化mock、ctx、path等变量 fileManagerMock.EXPECT(). ReadAllBy(params.ctx, path, isLogFilter()).Return(files, nil) // 调用待测试的Service函数 Service() }
方案二:给Filter添加可识别标识(适合复杂场景)
如果原ByExtension的逻辑难以通过行为验证,可以修改实现,让生成的Filter携带可识别的元数据,比如用结构体包装函数:
// 修改FileFilter为结构体类型,保留函数调用能力 type FileFilter struct { Identifier string FilterFunc func(*models.File) bool } // 实现函数调用方法,保持原有接口兼容 func (f FileFilter) Apply(file *models.File) bool { return f.FilterFunc(file) } // 修改ByExtension,生成带标识的Filter func ByExtension(ext string) FileFilter { return FileFilter{ Identifier: "extension:" + ext, FilterFunc: func(file *models.File) bool { return file.Extension == ext }, } } // 同步修改FileManager接口的参数类型 type FileManager interface { ReadAllBy(ctx context.Context, path models.Path, filters ...FileFilter) ([]*models.File, error) }
此时测试时可直接校验Filter的标识:
fileManagerMock.EXPECT(). ReadAllBy(params.ctx, path, mock.MatchedBy(func(filter FileFilter) bool { return filter.Identifier == "extension:log" })).Return(files, nil)
原测试不生效的原因
mock.AnythingOfType("FileFilter")仅检查参数是否属于FileFilter类型,不管这个函数是ByExtension("log")还是ByExtension("txt")生成的,都会通过断言,因此传错Filter也不会触发测试失败。
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

