单元测试TLS客户端

I have a function that makes an https request to a TLS server. I want to write unit tests to test the client function. I came across httptest.NewTLSServer that can be used to mock the server. But, how can I incorporate the certificates that the client uses instead of the default ones used in NewTLSServer?

Following is the client function that makes the request:

func MakeDownloadRequest(url string) (*http.Response, error) {

    caCert, err := ioutil.ReadFile("client/tlscerts/cert.pem")
    if err != nil {
        return nil, err
    }
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)

    cert, err := tls.LoadX509KeyPair("client/tlscerts/cert.pem","client/tlscerts/key.pem")
    if err != nil {
        return nil, err
    }

    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                RootCAs:      caCertPool,
                Certificates: []tls.Certificate{cert},
            },
        },
    }

    resp, err := client.Get(url)
    if err != nil {
        return nil, err
    }
    return resp, nil
}

Server stub:

server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        io.WriteString(w, "Hello")
    }))

Using the server.URL to make requests gives me "bad certificate" error. How can I make both the client and server use the same certificate?

Instead of using NewTLSServer() you want to:

  • Create your test server via httptest.NewUnstartedServer()
  • Create a *tls.Config much like you did in the code that sets up your http.Client in your MakeDownloadRequest()
  • Set the test server's TLS field to the *tls.Config created in the previous step
  • Start the test server using its StartTLS() method

Then your program should be able to call into your test server using those certificates.