Closed jiahuat closed 4 years ago
If the mock function has a return value, how could I get it?
Wait a minute, I'll show you a demo.
If the mock function has a return value, how could I get it?
import (
"fmt"
sm "github.com/cch123/supermonkey"
)
func patchFuncSymbol() {
fmt.Println(heyHeyHey())
var res string
patchGuard := sm.PatchByFullSymbolName("main.heyHeyHey", func() string {
res = func() string {
// Do what you want ....
return "Are you ok?"
}()
return res
})
fmt.Println(heyHeyHey())
fmt.Println(res)
patchGuard.Unpatch()
}
//go:noinline
func heyHeyHey() string {
return "I'm not ok!"
}
I hope it will help you.
感谢你的回答! 实际情况比上面的栗子复杂点。我想mock一个grpc call。grpc方法大致如下: MyFunc(ctx context.Context, in SearchRequest, opts ...grpc.CallOption) (SearchResponse, error) 实现如下: patchGuard := sm.PatchByFullSymbolName("xxxxxxx.pb.path.(Client).MyFunc", func(ctx context.Context, in pb.SearchRequest, opts ...grpc.CallOption) (pb.SearchResponse, error) { // 注意⚠️这个返回值类型 result := &pb.SearchResponse{Data: some mock data} return result, nil }) 期望的是在涉及调用MyFunc的时候 都返回mock中的result, 实际上在运行中,获取到的SearchResponse都是nil; 奇怪的是 将PatchFunc中的 方法的返回值类型改为 interface{}, 成功获取到了期望中mock的result,改变后的PatchFunc签名如下: func(ctx context.Context, in pb.SearchRequest, opts ...grpc.CallOption) (interface{}, error)
按照supermock的设计,如果签名不对应该会报错的吧,目前这个现象有点迷惑
感谢你的回答! 实际情况比上面的栗子复杂点。我想mock一个grpc call。grpc方法大致如下: MyFunc(ctx context.Context, in SearchRequest, opts ...grpc.CallOption) (SearchResponse, error) 实现如下: patchGuard := sm.PatchByFullSymbolName("xxxxxxx.pb.path.(Client).MyFunc", func(ctx context.Context, in pb.SearchRequest, opts ...grpc.CallOption) (pb.SearchResponse, error) { // 注意⚠️这个返回值类型 result := &pb.SearchResponse{Data: some mock data} return result, nil }) 期望的是在涉及调用MyFunc的时候 都返回mock中的result, 实际上在运行中,获取到的SearchResponse都是nil; 奇怪的是 将PatchFunc中的 方法的返回值类型改为 interface{}, 成功获取到了期望中mock的result,改变后的PatchFunc签名如下: func(ctx context.Context, in pb.SearchRequest, opts ...grpc.CallOption) (interface{}, error)
按照supermock的设计,如果签名不对应该会报错的吧,目前这个现象有点迷惑
方便上传到仓库看下这个demo吗?感觉你这种写法应该是没有问题的。
这个涉及到公司项目 不方便上传,如果你那边方便的话 不知道是否可以加下微信好友,我们私下沟通:940311859
你尝试以下两种方式,不行的话再Call我哦。
1. Please add -l to your gcflags
> go run -gcflags="-l" yourfile.go
2. Add `//go:noinline` to func which you want to patch.
//go:noinline
func MyFunc(ctx context.Context, in *SearchRequest, opts ...interface{}) (*SearchResponse, error) {
这个涉及到公司项目 不方便上传,如果你那边方便的话 不知道是否可以加下微信好友,我们私下沟通:940311859
我使用跟你同一种方式去patch是ok的,应该就是代码内联的问题。
- 是跑的test :go test -ldflags="-s=false" -gcflags=-l
- 那个方法是grpc call, protoc-gen-go 自动生成的,如果在这个文件上面做修改的话 感觉不太好
麻烦你单独拎出来一个可测的demo吧,proto+test几个文件就好。
这个涉及到公司项目 不方便上传,如果你那边方便的话 不知道是否可以加下微信好友,我们私下沟通:940311859
加你了,通过下
When I tried it out, it seemed to work.
type SearchRequest struct {
Req string
}
type SearchResponse struct {
Resp string
}
type A struct {}
func (*A) MyFunc(ctx context.Context, in *SearchRequest, opts ...interface{}) (*SearchResponse, error) {
return nil, nil
}
// Original func signature
func (*A) MyFunc(ctx context.Context, in *SearchRequest, opts ...interface{}) (*SearchResponse, error)
// PatchByFullSymbolName
func (_ *A, ctx context.Context, in *pb.SearchRequest, opts ...interface {}) (*pb.SearchResponse, error)
// or
func (_ uintptr, ctx context.Context, in *pb.SearchRequest, opts ...interface {}) (*pb.SearchResponse, error)
// code
sm.Patch((*pb.A).MyFunc, func(_ uintptr, ctx context.Context, in *pb.SearchRequest, opts ...interface{}) (*pb.SearchResponse, error) {
return nil, nil
})
sm.PatchByFullSymbolName("pb.(*A).MyFunc", func(_ uintptr, ctx context.Context, in *pb.SearchRequest, opts ...interface{}) (*pb.SearchResponse, error) {
return nil, nil
})
Yes, it worked, Thanks a lot!
If the mock function has a return value, how could I get it?