如何在GRPC服务器实现中模拟Grpc客户端

时间:2019-10-23 11:28:20

标签: performance unit-testing go grpc grpc-go

我有一个正在与许多其他GRPC服务器通信的GRPC服务器。 因此,我的服务器是许多其他GRPC服务器的客户端 我想测试我的服务器实现,但仍坚持如何模拟GRPC客户端。

我的GRPC服务器中有一个这样的方法:

func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    user, err := api.NewUserServiceClient(conn).
        UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

在这种类型的实现中,我无法模拟UserServiceClient,因为我在方法:(

我已经考虑了解决此问题的两种方法

  1. UserBackendServer结构内具有客户端引用
type UserBackendServer struct {
    projectID string
    userSvcClient api.UserServiceClient
}

func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    user, err := s.userSvcClient.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

使用此实现,我的副作用是与客户端保持持续活动的连接(我想与10个客户端进行通信)。生产上好吗?拥有始终保持连接状态的客户端会导致内存泄漏或并发连接过多吗?

  1. 使用将客户端作为参数的方法
func (s UserBackendServer) UpdateUser(ctx context.Context, req *api.UpdateUserRequest) (*api.User, error) {
    conn, err := grpc.DialContext(ctx, s.userSvcAddr,
        grpc.WithInsecure(),
        grpc.WithStatsHandler(&ocgrpc.ClientHandler{}))
    if err != nil {
        return nil, fmt.Errorf("could not connect shipping service: %+v", err)
    }
    defer conn.Close()

    client := api.NewUserServiceClient(conn)
    updateUser(ctx, req.UserId, req.User, client)


    user, err := s.userSvcClient.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })
    return user, nil
}

func updateUser(ctx context.Context, userId string, user *api.User, client api.UserServiceClient) (*api.User, error){
    userUpdated, err := client.UpdateUser(ctx, &api.UpdateUserRequest{
        User:                 nil,
        UserId:               "",
    })

    return userUpdated, err
}

编写所有这些小功能似乎有点麻烦,而且我无法对服务器功能进行单元测试。

第一策略可行吗?您是否有有关限制的经验,或者如果在服务器结构中维护了连接,如何重试失败的连接

0 个答案:

没有答案