title: Go gRPC server make integration tests fail
body: <p>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.</p>
  
  <p>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:</p>
  
  <pre><code>func main() {
      server := startHTTPServer()
      defer server.Close()
  
      c := make(chan os.Signal, 1)
      signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
  
      &lt;-c
      log.Println("Stopped")
  }
  
  func startHTTPServer() *http.Server {
      http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
          w.WriteHeader(http.StatusOK)
      })
  
      server := &amp;http.Server{
          Addr: net.JoinHostPort("", strconv.Itoa(livelinessPort)),
      }
  
      go server.ListenAndServe()
  
      return server
  }
  </code></pre>
  
  <p>and I tested in this way, following <a href="http://cs-guy.com/blog/2015/01/test-main/" rel="nofollow noreferrer">this article</a>:</p>
  
  <pre><code>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 := &amp;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
      }
  }
  </code></pre>
  
  <p>and so far so good:</p>
  
  <pre><code>$ go test
  PASS
  2018/08/13 09:23:16 Stopped
  ok      github.com/...        0.015s
  </code></pre>
  
  <p>Te problem is when I try to add the gRPC server in the main application, following <a href="https://grpc.io/docs/tutorials/basic/go.html" rel="nofollow noreferrer">gPRC go examples</a>. I've added this to my main file</p>
  
  <pre><code>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, &amp;checksServiceServer{})
  
      grpcServer.Serve(lis)
      log.Println("Started grpc server")
      return grpcServer
  }
  </code></pre>
  
  <p>but now when I run the test, it fails after the actual test was run, when the interrupt signal is sent.</p>
  
  <pre><code>$  go test 
  PASS
  signal: interrupt
  FAIL    github.com/...        0.016s
  </code></pre>
  
  <p>I made some tests and this is not depending by the actual test (as it pass with a test function that just <code>return</code>, and it's working while running the test suite using goLand:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>--- <strong>EDIT</strong></p>
  
  <p>I found that the problem is around the listener. Having in the main function:</p>
  
  <pre><code>func main() {
      net.Listen("tcp", fmt.Sprintf(":%d", serverPort))
      c := make(chan os.Signal, 1)
      signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
  
      &lt;-c
      log.Println("Stopped")
  }
  </code></pre>
  
  <p>and a test with just a return (with the same setup of the previous one) will cause the test to fail: </p>
  
  <pre><code>$ go test -v
  === RUN   Test2
  --- PASS: Test2 (0.00s)
  PASS
  signal: interrupt
  FAIL    github.com/[...]        0.014s
  </code></pre>