英文:
grpc testing code exit 1 with 'rpc error: code = Unimplemented desc = method Hello not implemented'
问题
环境
go version go1.17.4 linux/amd64
libprotoc 3.6.1
问题
我正在测试使用Go实现的gRPC服务器和客户端。
首先,我制作了proto定义,并通过protoc命令生成了pb代码。
我参考了这个解决方案。
下面的错误是通过最小的代码来重现我的错误。
错误
$ go test
--- FAIL: TestHello (0.00s)
main_test.go:49: failed to Hello: rpc error: code = Unimplemented desc = method Hello not implemented
FAIL
exit status 1
FAIL github.com/Asuha-a/test/test 0.003s
代码
hello.proto
syntax = "proto3";
option go_package = "github.com/Asuha-a/test/pb";
package hello;
service Hello {
rpc Hello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string foo = 1;
}
message HelloReply {
string bar = 1;
}
main_test.go
package hello_test
import (
"context"
"log"
"net"
"testing"
"github.com/Asuha-a/test/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
)
type server struct {
pb.UnimplementedHelloServer
}
const bufSize = 1024 * 1024
var lis *bufconn.Listener
func init() {
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
pb.RegisterHelloServer(s, &server{})
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("server exited with error: %v", err)
}
}()
}
func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial()
}
func TestHello(t *testing.T) {
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to dial bufnet: %v", err)
}
defer conn.Close()
client := pb.NewHelloClient(conn)
r, err := client.Hello(ctx, &pb.HelloRequest{
Foo: "foo",
})
if err != nil {
t.Fatalf("failed to Hello: %v", err) //49th line prints the error
}
log.Println(r)
}
英文:
Environment
go version go1.17.4 linux/amd64
libprotoc 3.6.1
Problem
I'm testing grpc server and client implemented by Go.
First, I made proto definition and generate pb codes by protoc command.
I referred this solution.
Following the error is printed by minimum codes to reproduce my error.
Error
$ go test
--- FAIL: TestHello (0.00s)
main_test.go:49: failed to Hello: rpc error: code = Unimplemented desc = method Hello not implemented
FAIL
exit status 1
FAIL github.com/Asuha-a/test/test 0.003s
Code
hello.proto
syntax = "proto3";
option go_package = "github.com/Asuha-a/test/pb";
package hello;
service Hello {
rpc Hello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string foo = 1;
}
message HelloReply {
string bar = 1;
}
main_test.go
package hello_test
import (
"context"
"log"
"net"
"testing"
"github.com/Asuha-a/test/pb"
"google.golang.org/grpc"
"google.golang.org/grpc/test/bufconn"
)
type server struct {
pb.UnimplementedHelloServer
}
const bufSize = 1024 * 1024
var lis *bufconn.Listener
func init() {
lis = bufconn.Listen(bufSize)
s := grpc.NewServer()
pb.RegisterHelloServer(s, &server{})
go func() {
if err := s.Serve(lis); err != nil {
log.Fatalf("server exited with error: %v", err)
}
}()
}
func bufDialer(context.Context, string) (net.Conn, error) {
return lis.Dial()
}
func TestHello(t *testing.T) {
ctx := context.Background()
conn, err := grpc.DialContext(ctx, "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
if err != nil {
t.Fatalf("failed to dial bufnet: %v", err)
}
defer conn.Close()
client := pb.NewHelloClient(conn)
r, err := client.Hello(ctx, &pb.HelloRequest{
Foo: "foo",
})
if err != nil {
t.Fatalf("failed to Hello: %v", err) //49th line prints the error
}
log.Println(r)
}
答案1
得分: 3
在你的测试中,你使用 server
结构体调用了 pb.RegisterHelloServer(s, &server{})
。然而,这个结构体只嵌入了 pb.UnimplementedHelloServer
,并且没有声明任何方法。因此,当调用它的任何 RPC 时,你只能得到 codes.Unimplemented
的返回值。
你需要在 server
结构体上实现 Hello
RPC:
func (s *server) Hello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{}, nil
}
**注意:**嵌入 pb.UnimplementedHelloServer
可以使 gRPC 服务器实现向前兼容,但会牺牲编译时检查的功能。如果要放弃向前兼容性并在编译时捕获这些错误,可以改为嵌入 pb.UnsafeHelloServer
。
英文:
In your test you are calling pb.RegisterHelloServer(s, &server{})
using the server
struct. However this struct only embeds pb.UnimplementedHelloServer
and declares no methods. Hence, you can only get codes.Unimplemented
back when calling any of its RPCs.
You have to implement the Hello
rpc on the server
struct:
func (s *server) Hello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{}, nil
}
Note: embedding pb.UnimplementedHelloServer
makes the gRPC server implementations forward compatible at the expense of compile-time checks. To forgo forward compatibility and catch these errors at compile time, you can embed instead pb.UnsafeHelloServer
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论