It can be tough to get anywhere close to 100% code coverage when funcs in the “stdlib” can’t be forced to error. This post takes you through several of the common funcs built in to golang and shows you how to trigger an error to help you bump up your code coverage. This list is short and skews heavily toward http, where I spend most of my time.

encoding/json.Marshal

Marshal any func, chan, or complex:

serialized, err := json.Marshal(func(){})

See in the playground

net/url.Parse()

Pass invalid hex strings:

u, err := url.Parse("%zzzzz")

See in the playground

See unit tests for unescape

net/http.NewRequest()

The url in NewRequest() also goes through url.Parse(), so we can reuse our url breaking tricks.

r, err := http.NewRequest("GET","/%zz", nil)

See in the playground

net/http.ListenAndServe()

We can pass an invalid port number to trip up ListenAndServe(). Full working example this time since this won’t run in the playground.

package main

import (
  "net/http"
  "log"
)

func main() {
  h := func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte(`Hello World`))
  }
  http.HandleFunc("/", h)
  log.Fatal(http.ListenAndServe(":9999999", nil))
}

If choosing the port is not an option, we can cheat on our unit test, and block that port on the host. However, the stdlib doesn’t support this in any form, so you’d have to pick a stoppable http server like tylerb/graceful, like so:

package main

import (
  "fmt"
  "net/http"

  "gopkg.in/tylerb/graceful.v1"
)

func main() {
  // First block the port we care about
  h1 := func(w http.ResponseWriter, r *http.Request) {
    w.Write([]bytes(`Blocked`))
  }
  srv := &graceful.Server{
    Timeout: 5 * time.Second,
    Server: &http.Server{
      Addr: ":1234",
      Handler: http.HandlerFunc(h1)
    },
  }
  srv.ListenAndServe()

  // Now try to use the blocked port
  h2 := func(w http.ResponseWriter, r *http.Request) {
    w.Write([]bytes(`Blocked`))
  }
  fmt.Println(http.ListenAndServe(":1234", http.HandlerFunc(h2))

  // Stop the blocking server
  srv.Stop()
}

net/http.Client

Often, you want a way to force a connection error to simulate problems with some API you’re consuming as part of your service. Golang’s stdlib provides the RoundTripper interface to allow us to customize interaction with the network.

package main

import (
  "errors"
  "fmt"
  "net/http"
)

// Force errors or responses of our choosing to be returned
type mock struct {}
func (s *mock) RoundTrip(r *http.Request) (*http.Response, error) {
  return nil, errors.New("Unable to connect")
}

func main() {
  client := &http.Client{ &mockRoundTripper{}, nil, nil, 0 }
  resp, err := client.Get("https://www.google.com")
  fmt.Println("resp=", resp)
  fmt.Println("err=", err)
}

What Else?

If you run into a golang func that you can’t break, post it in the comments here or tweet it to me.