测试使用TWIRP开发的RPC服务

Test RPC service developed in using TWIRP

我想测试一个示例 Twirp RPC 服务。示例服务来自 Twirp official website.

Protobuf定义如下:

syntax = "proto3";

package helloservice;
option go_package = "helloservice";

service HelloWorld {
  rpc Hello(HelloReq) returns (HelloResp);
}

message HelloReq {
  string subject = 1;
}

message HelloResp {
  string text = 1;
}

服务器实现:

type HelloWorldServer struct{}

func (s *HelloWorldServer) Hello(ctx context.Context, req *pb.HelloReq) (*pb.HelloResp, error) {
    return &pb.HelloResp{Text: "Hello " + req.Subject}, nil
}

我尝试了 ,但 ClientConn 与 HTTPClient 之间存在一些混淆。到目前为止,我有这个

var Once sync.Once
const bufSize = 1024 * 1024
var listener *bufconn.Listener

func InitTestServer(t *testing.T) *gomock.Controller {
    Once.Do(func(){
        listener = bufconn.Listen(bufSize)
        server := &server.HelloWorldServer{}
        twirpHandler := pb.NewHelloWorldServer(server, nil)
        mux := http.NewServeMux()
        mux.Handle(twirpHandler.PathPrefix(), twirpHandler)
        httpServer := http.Server{
            Handler: mux,
        }
        go func() {
            if err := httpServer.Serve(listener); err != nil {
                if err != http.ErrServerClosed {
                    log.Fatalln("Failed to start http listener", "error", err)
                }
            }
        }()
    })
    ctrl := gomock.NewController(t)
    return ctrl
}

func bufDialer(context.Context, string) (net.Conn, error) {
    return listener.Dial()
}

func TestCreate(t *testing.T) {
    //ctrl := InitTestServer(t)
    InitTestServer(t)
    ctx := context.Background()
    conn, err := grpc.DialContext(ctx, "", grpc.WithInsecure(), grpc.WithContextDialer(bufDialer))
    // conn is of type *ClientConn
    if err != nil {
        t.Fatalf("Failed to dial bufnet: %v", err)
    }
    defer conn.Close()
    //NewHelloWorldJSONClient accepts only HTTPClient
    client := pb.NewHelloWorldJSONClient(conn)
    response, err := client.Hello(ctx, &pb.HelloReq{
        Subject: "sample",
    })
    t.Log(response, err)
}

有什么方法可以将一种转换成另一种,或者有什么方法可以测试 Twirp RPC?

您可以使用 net/http/httptest 完成此类测试。

  1. 使用 pb.NewHelloWorldServer 创建处理程序并为其提供服务器实现结构。
  2. 使用处理程序创建 httptest.NewServer
  3. pb.NewHelloWorldJSONClient(或 protobuf,或两者)中使用 httptest 服务器的 .URL

举个简单的例子:

package main

import (
    "context"
    "net/http"
    "net/http/httptest"
    "testing"

    pb "github.com/3ventic/twirphelloworld/rpc"
)

// InitTestServer initializes a test server for HelloWorld and returns its address
func InitTestServer() string {
    handler := pb.NewHelloWorldServer(&HelloWorldServer{})
    server := httptest.NewServer(handler)
    return server.URL
}

func TestHello(t *testing.T) {
    url := InitTestServer()
    clients := map[string]pb.HelloWorld{
        "json": pb.NewHelloWorldJSONClient(url, http.DefaultClient),
        "pb":   pb.NewHelloWorldProtobufClient(url, http.DefaultClient),
    }

    for typ, client := range clients {
        t.Run(typ, func(t *testing.T) {
            ctx := context.Background()
            result, err := client.Hello(ctx, &pb.HelloReq{
                Subject: "test",
            })
            if err != nil {
                t.Error(err)
                t.FailNow()
            }
            if result.Text != "Hello test" {
                t.Errorf("result didn't match 'Hello test', was '%s'", result.Text)
            }
        })
    }
}

Full example available here