douyong1905 2018-08-13 09:26
浏览 219
已采纳

使用gRPC服务器使集成测试失败

I recently started to play again with go, and my task at the moment is to implement a service (that will run on k8s) that should act as a gRPC server.

As per requirements, at the moment, to satisfy the readinessProbe on k8s, I need to implement an healthcheck endpoint for my service, and this should be tested: what I've done is:

func main() {
    server := startHTTPServer()
    defer server.Close()

    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

    <-c
    log.Println("Stopped")
}

func startHTTPServer() *http.Server {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.WriteHeader(http.StatusOK)
    })

    server := &http.Server{
        Addr: net.JoinHostPort("", strconv.Itoa(livelinessPort)),
    }

    go server.ListenAndServe()

    return server
}

and I tested in this way, following this article:

func TestMain(m *testing.M) {
    flag.Parse()

    wg := setup()

    result := m.Run()

    shutdown(wg)

    os.Exit(result)
}

func shutdown(wg *sync.WaitGroup) {
    syscall.Kill(syscall.Getpid(), syscall.SIGINT)
    wg.Wait()
}

func setup() *sync.WaitGroup{
    os.Setenv("APP_ENV", EnvTest)

    wg := &sync.WaitGroup{}
    startMainProcess(wg)
    return wg
}

func startMainProcess(wg *sync.WaitGroup) {
    go func() {
        wg.Add(1)
        defer wg.Done()
        main()
    }()
}

func TestK8SHealth(t *testing.T) {
    res, err := http.Get("http://:8080/")
    if err != nil {
        t.Errorf("Unexpected API error: %s", err)
        return
    }

    defer res.Body.Close()

    if res.StatusCode != http.StatusOK {
        t.Errorf("Unexpected status code: %d", res.StatusCode)
        return
    }
}

and so far so good:

$ go test
PASS
2018/08/13 09:23:16 Stopped
ok      github.com/...        0.015s

Te problem is when I try to add the gRPC server in the main application, following gPRC go examples. I've added this to my main file

func main() {
    [...]

    startChecksServiceServer()

    [...]
}

func startChecksServiceServer() *grpc.Server {
    flag.Parse()
    lis, err := net.Listen("tcp", fmt.Sprintf(":%d", serverPort))
    if err != nil {
        log.Fatalf("Starting gPRC server error: failed to listen port %d: %v", serverPort, err)
    }

    grpcServer := grpc.NewServer()

    pb.RegisterChecksServiceServer(grpcServer, &checksServiceServer{})

    grpcServer.Serve(lis)
    log.Println("Started grpc server")
    return grpcServer
}

but now when I run the test, it fails after the actual test was run, when the interrupt signal is sent.

$  go test 
PASS
signal: interrupt
FAIL    github.com/...        0.016s

I made some tests and this is not depending by the actual test (as it pass with a test function that just return, and it's working while running the test suite using goLand:

GOROOT=/usr/local/go #gosetup
GOPATH=/Users/marco/Documents/projects/go #gosetup
/usr/local/go/bin/go test -c -i -o /private/var/folders/jh/znhv9f090yb7y390dckb23s00000gn/T/[...] #gosetup
/usr/local/go/bin/go tool test2json -t /private/var/folders/jh/znhv9f090yb7y390dckb23s00000gn/T/[...] -test.v -test.run
^TestK8SHealth$ #gosetup
=== RUN   TestK8SHealth
--- PASS: TestK8SHealth (0.00s)
PASS

Process finished with exit code 1

--- EDIT

I found that the problem is around the listener. Having in the main function:

func main() {
    net.Listen("tcp", fmt.Sprintf(":%d", serverPort))
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

    <-c
    log.Println("Stopped")
}

and a test with just a return (with the same setup of the previous one) will cause the test to fail:

$ go test -v
=== RUN   Test2
--- PASS: Test2 (0.00s)
PASS
signal: interrupt
FAIL    github.com/[...]        0.014s
  • 写回答

1条回答 默认 最新

  • doumeng9188 2018-08-15 20:04
    关注

    grpcServer.Serve(lis) is a blocking call. So like what you did with HTTP server go server.ListenAndServe(), you need to run it in a goroutine. Could you please try if go grpcServer.Serve(lis) will make the test pass?

    I am not sure about your new EDIT which indicates the problem is abut the listener. You can check whether net.Listen("tcp", fmt.Sprintf(":%d", serverPort)) returns or blocks.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 关于#python#的问题:自动化测试