欺骗 grpc UnaryHandler 在 Go 中进行 gRPC 单元测试

我正在努力提高 Go gRPC 服务器的覆盖范围,但在为服务器的拦截器功能编写测试时遇到了麻烦,因为我无法有意义地满足该UnaryHandler类型。


Interceptor我有一个具有以下签名的函数:


Interceptor func(

  ctx context.Context,

  req interface{},

  info *grpc.UnaryServerInfo,

  handler grpc.UnaryHandler, // <- my issue comes from here

) (interface{}, error)

我假设任何 gRPC 方法都会满足以下签名UnaryHandler:


type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)

所以我尝试传递带有此签名的方法:


GetToken(ctx context.Context, req *AuthData) (*Token, error)

我想象这会起作用,因为这就是拦截器实际上正在做的事情(转发该 RPC),但由于某种原因 Go 抱怨:


无法在拦截器的参数中使用 authService.GetToken (type func(context.Context, *AuthData) (*Token, error)) 作为类型 grpc.UnaryHandler


我继续编写了一个正确满足以下条件的虚拟函数:


func genericHandler(ctx context.Context, req interface{}) (interface{}, error) {

    return req, nil

}

这很好,因为我在测试拦截器时并不特别需要运行任何特定方法。然而,我很好奇为什么实际方法不满足约束,因为(根据我的理解)每当我在野外调用该 RPC 时,它都会被传递到底层的拦截器函数。


最可能的解释是 grpc UnaryHandler 没有做我想象的那样,但是它做了什么?


慕的地6264312
浏览 112回答 1
1回答

茅侃侃

不,函数GetToken(ctx context.Context, req *AuthData) (*Token, error)与以下类型不同type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)InGetToken第二个参数req的类型为*AuthData,而 inUnaryHandler req的类型为interface{}。返回的*Token类型与 不同interface{}。这就是为什么不能GetToken直接传递给拦截器的原因。在你的 grpc 服务中,你可以编写类似的方法GetToken(ctx context.Context, req *AuthData) (*Token, error)作为处理程序来完成您的服务器工作。然而,它并不UnaryHandler像人们想象的那样。大部分转换是由 grpc/protobuf 代码生成器完成的。根据您的原型定义,它会生成一个接口,如下所示:type XXXServer interface {&nbsp; &nbsp; GetToken(ctx context.Context, req *AuthData) (*Token, error)}您可以看到您的处理程序满足的是这个接口(而不是 UnaryHander)。在幕后,如果您查看xxx.pb.go生成的文件,您会发现一些_XXX_GetToken_Handler文件实际上正在执行处理程序工作。在此函数中,(实际)UnaryHandler被定义为:func _XXX_GetToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {&nbsp; &nbsp; // skip other preparations...&nbsp; &nbsp; //&nbsp;&nbsp; &nbsp; handler := func(ctx context.Context, req interface{}) (interface{}, error) {&nbsp; &nbsp; &nbsp; &nbsp; return srv.(XXXServer).GetToken(ctx, req.(*AuthData))&nbsp; &nbsp; }&nbsp; &nbsp; return interceptor(ctx, in, info, handler)}在 this 内部UnaryHandler,它将把您的服务器转换为接口XXXServer,然后调用您的处理程序(您的代码)。这显示了如何interceptor调用它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go