Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问如何实现一个通用的Mock函数? #109

Open
soluty opened this issue Sep 14, 2022 · 3 comments
Open

请问如何实现一个通用的Mock函数? #109

soluty opened this issue Sep 14, 2022 · 3 comments

Comments

@soluty
Copy link

soluty commented Sep 14, 2022

在做单元测试的情况下, 会有一种需求是, 确定调用了某个函数,或者某个接口, 其它的mock框架基本都提供这种能力, gomonkey也可以, 但是需要一个一个的模拟, 有没有可能通过1.18的泛型, 写一个类似这样的Func结构
type Func[T any] struct {
callCount int
}
然后有这样的方法 MockFunc[T any](ps *Patches, f T) *Func[T]

那么对于只需要知道方法有没有调用的情况下, 就可以直接用这个通用的Mock结构, 甚至更进一步, 在Func中还可以存储调用的入参, 在单测中就可以精确的知道入参了.

我尝试着实现了一下我的想法, 但是由于我对反射理解有些欠缺, 所以没能完成这个, 你觉得这个想法能实现吗?
如果可以,能否做为feature加到gomonkey中?

@soluty
Copy link
Author

soluty commented Sep 14, 2022

好像不算特别麻烦, 下面的代码可以对函数的调用进行通用mock, 我再想想Api的设计, 看看可不可以基于gomonkey有一个方便的对函数和接口的被调用的包

type Func struct {
call bool
params []interface{}
}

func MockFunc[F any](ps *gomonkey.Patches, f F) *Func {
ret := &Func{}
typ := reflect.TypeOf(f)
if typ.Kind() != reflect.Func {
panic("f must be a function")
}
rFn := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) {
for i := 0; i < typ.NumIn(); i++ {
ret.params = append(ret.params, args[i].Interface())
}
return
})
ps.ApplyFunc(f, rFn.Interface())
return ret
}

@soluty
Copy link
Author

soluty commented Sep 14, 2022

好像这个泛型没啥用..不如直接用interface

好像不算特别麻烦, 下面的代码可以对函数的调用进行通用mock, 我再想想Api的设计, 看看可不可以基于gomonkey有一个方便的对函数和接口的被调用的包

type Func struct { call bool params []interface{} }

func MockFunc[F any](ps *gomonkey.Patches, f F) *Func { ret := &Func{} typ := reflect.TypeOf(f) if typ.Kind() != reflect.Func { panic("f must be a function") } rFn := reflect.MakeFunc(typ, func(args []reflect.Value) (results []reflect.Value) { for i := 0; i < typ.NumIn(); i++ { ret.params = append(ret.params, args[i].Interface()) } return }) ps.ApplyFunc(f, rFn.Interface()) return ret }

好像这个泛型没啥用, 直接用interface{}就可以了

@xhd2015
Copy link

xhd2015 commented Mar 18, 2024

xgo刚好支持通用的拦截器: https://github.com/xhd2015/xgo?tab=readme-ov-file#usage

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants