当前位置: 首页 > 知识库问答 >
问题:

欺骗grpc UnaryHandler用于Go中的gRPC单元测试

解宏扬
2023-03-14

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

我有一个带有以下签名的函数拦截器

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(类型func(上下文。上下文,*AuthData)(*Token,错误))作为grpc类型。UnaryHandler在Interceptor的参数中

我继续写了一个虚拟函数,它正确地满足:

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

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

最有可能的解释是,grpc UnaryHandler不做我认为它做的事情,但它做什么呢?

共有1个答案

陆昕
2023-03-14

不,是功能

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

不是和

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

GetToken中,第二个参数req的类型为*AuthData,而在UnaryHandlerreq的类型为接口{}。返回的*Token接口{}不是同一类型。这就是您无法将GetToken直接传递给拦截器的原因。

在grpc服务中,您可以编写如下方法

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

作为处理程序来完成您的服务器工作。但是,它不是人们可能认为的UnaryHandler

大部分转换由grpc/protobuf代码生成器完成。根据您的原型定义,它生成一个接口,如下所示:

type XXXServer interface {
    GetToken(ctx context.Context, req *AuthData) (*Token, error)
}

您可以看到,您的处理程序满足的是这个接口(而不是非惯用者)。

在引擎盖下,如果你看一下生成的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界面,然后调用您的处理程序(您的代码)。这显示了如何调用拦截器。

 类似资料:
  • 我正在尝试使用yii2 codeception。我有一个名为Client的类,它扩展了ActiveRecord。 规则()函数: 我在tests\codeception\unit\models文件夹中创建了一个名为ClientTest的文件,该文件包含以下内容: 当我使用“codecept run unit--debug”命令运行测试时,我看到

  • 我在使用Yii2进行Codeception时遇到了一些问题。我刚刚升级到Yii 2.0.10,一直在使用本指南 我收到错误:

  • 我正在编写一组简单的PHP函数,我只使用纯PHP7,没有框架,什么都没有。这些函数稍后将在CMS中的插件中使用,但这不是重点。我想使用Codeception为我的函数编写单元测试(为了熟悉它,我知道Codeception基本上只在这里运行PHPUnit),但我真的不知道如何以合理的方式将Codeception指向我的代码。 我的结构如下:我有,其中包含我想要测试的函数,大致如下: 我使用Compo

  • 2.6. 欺骗表单提交 制造一个欺骗表单几乎与假造一个URL一样简单。毕竟,表单的提交只是浏览器发出的一个HTTP请求而已。请求的部分格式取决于表单,某些请求中的数据来自于用户。 大多数表单用一个相对URL地址来指定action属性: <form action="process.php" method="POST"> 当表单提交时,浏览器会请求action中指定的URL,同时它使用当前的URL地址

  • ARP欺骗是一种在局域网中常用的攻击手段,目的是让局域网中指定的(或全部)的目标机器的数据包都通过攻击者主机进行转发,是实现中间人攻击的常用手段,从而实现数据监听、篡改、重放、钓鱼等攻击方式。 在进行ARP欺骗的编码实验之前,我们有必要了解下ARP和ARP欺骗的原理。 3.1.1 ARP和ARP欺骗原理 ARP是地址转换协议(Address Resolution Protocol)的英文缩写,它是

  • 我正在尝试使用Codeception进行基本的单元测试。没有使用任何框架。 我的工作根目录如下: 在 我的测试用例是: 我的composer.json中还有: 当我跑的时候