我正在努力提高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)

我以为这会起作用,因为这是Interceptor实际所做的(转发RPC),但是出于某些原因,Go提示道:



我继续写了一个可以正确满足的虚拟函数:
func genericHandler(ctx context.Context, req interface{}) (interface{}, error) {
    return req, nil
}

很好,因为在测试拦截器时我不需要特别运行任何特定方法。但是我对为什么实际方法不能满足约束感到好奇,因为(据我的理解)每当我在野外调用该RPC时,该方法都会被传递给Interceptor函数。

最可能的解释是,grpc UnaryHandler并没有按照我的想法执行,但是随后又会执行什么呢?

最佳答案

不,功能

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

与以下类型不同
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)

GetToken中,第二个参数req*AuthData类型,而在UnaryHandler中,reqinterface{}类型。返回的*Tokeninterface{}的类型不同,两者也不相同。这就是为什么您不能直接将GetToken传递给拦截器的原因。

在grpc服务中,您将编写类似
GetToken(ctx context.Context, req *AuthData) (*Token, error)

作为服务器的处理程序。但是,它并不是人们可能认为的UnaryHandler

大多数转换是由grpc/protobuf代码生成器完成的。根据您的原始定义,它会生成一个接口(interface),如下所示:
type XXXServer interface {
    GetToken(ctx context.Context, req *AuthData) (*Token, error)
}

您可以看到您的处理程序满足的就是此接口(interface)(不是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) {
    // skip other preparations...
    //
    handler := func(ctx context.Context, req interface{}) (interface{}, error) {
        return srv.(XXXServer).GetToken(ctx, req.(*AuthData))
    }
    return interceptor(ctx, in, info, handler)
}

在此UnaryHandler内部,它将把您的服务器转换到XXXServer接口(interface),然后调用您的处理程序(您的代码)。这说明了如何调用interceptor

关于go - 欺骗grpc UnaryHandler以在Go中对gRPC进行单元测试,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57681271/

10-12 17:53