我正在努力提高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
中,req
是interface{}
类型。返回的*Token
与interface{}
的类型不同,两者也不相同。这就是为什么您不能直接将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/