尝试在 TCP 侦听器上提供服务时,由于超时,Go 测试明显失败

我有这个单元测试:


func TestServer(t *testing.T) {

    db := prepareDBConn(t)

    defer db.Close()

    lis := bufconn.Listen(1024 * 1024)

    t.Logf("Opened listener: %v", lis)


    grpcServer := grpc.NewServer(

        withUnaryInterceptor(),

    )

    t.Logf("Opened grpc server: %v", grpcServer)

    signKey := getSignKey()

    if signKey == nil {

        t.Fatal("Failed to find or parse RSA private key")

    }


    verifyKeyErr := setVerifyKey()

    if verifyKeyErr != nil {

        t.Fatal("Failed to find or parse RSA public key")

    }


    pb.RegisterAuthServiceServer(grpcServer, newAuthServiceServer(db, signKey))


    err := grpcServer.Serve(lis)

    if err != nil {

        t.Fatalf("Failed to listen: %+v", err)

    }

}

如果我注释掉最后 4 行:


    // err := grpcServer.Serve(lis)

    // if err != nil {

    //   t.Fatalf("Failed to listen: %+v", err)

    // }

每次都会通过,但无论出于何种原因,它都会在线路上变得很糟糕err := grpcServer.Server(lis)。我尝试过使用真正的 TCP 侦听器(lis := bufconn.Listen与交换lis := net.Listen("tcp"))。

它没有告诉我出了什么问题(除了超时)并且似乎还参考了其他库的测试?我通过调用测试vs-code,它使用以下命令:

/usr/local/bin/go test -timeout 30s -run ^(TestServer)$

我可以构建并运行该包,它完全按照我的预期工作,并且不会在那条线上失败,所以我认为我在单元测试方面做错了一些事情,但在这一点上我没有太多要做的,而且我不这样做对 go 测试了解不多。


慕后森
浏览 106回答 2
2回答

哆啦的时光机

正如我所看到的,您正在尝试对 gRPC 服务器进行单元测试。您尝试使用的策略对于单元测试来说是相当过大的。为简单起见,您应该有一个服务器结构来保存互连的部分,例如:数据库连接。因此,您只需初始化数据库连接并将其传递给服务器结构。这是模拟数据库的正确位置。之后,您将拥有启动 gRPC 服务器实例,因为您不需要拨打 gRPC 进行单元测试。然后,您可以在初始化的 Server 实例上调用预期的 rpc 函数。它看起来更加干净和可维护。

富国沪深

服务是一个阻塞调用。它将等待新的连接并在它们进来时无限期地处理它们。这就是它的全部目的 - 在服务器关闭或崩溃之前它不会返回。根据文档Serve:Serve 接受监听器上的传入连接,为每个连接创建一个新的 ServerTransport 和服务 goroutine。服务 goroutine 读取 gRPC 请求,然后调用注册的处理程序来回复它们。当 lis.Accept 因致命错误而失败时,Serve 返回。对于您的其他问题:它没有告诉我出了什么问题(除了超时)这就是问题所在。go test有时间限制,而测试超过了时间。其实没有什么可说的了。它提供了堆栈跟踪,这有助于确定超时的原因,因为它们告诉您每个 goroutine 超时时的位置(例如 goroutine 5 正在等待新连接Listener.Accept)。似乎也参考了其他库的测试不是测试(那些将在_test.go文件中),只是代码引用的库中的代码。它们是堆栈跟踪,通常包含来自标准库和/或第三方库的代码,因为它是跟踪时该 goroutine 的调用堆栈的一部分。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go