Home >Backend Development >Golang >How to Unit Test HTTP Calls in Go using the `httptest` Package?
How to Test HTTP Calls in Go with httptest
Introduction
Unit testing is a crucial aspect of software development, and for Go programs, the httptest package provides a useful tool for testing HTTP calls. This article will demonstrate how to employ httptest to write unit tests for your Go code that makes HTTP requests.
The Challenge
Consider the following Go code:
package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "time" ) type twitterResult struct { Results []struct { Text string `json:"text"` Ids string `json:"id_str"` Name string `json:"from_user_name"` Username string `json:"from_user"` UserId string `json:"from_user_id_str"` } } var ( twitterUrl = "http://search.twitter.com/search.json?q=%23UCL" pauseDuration = 5 * time.Second ) func retrieveTweets(c chan<- *twitterResult) { for { resp, err := http.Get(twitterUrl) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) r := new(twitterResult) //or &twitterResult{} which returns *twitterResult err = json.Unmarshal(body, &r) if err != nil { log.Fatal(err) } c <- r time.Sleep(pauseDuration) } } func displayTweets(c chan *twitterResult) { tweets := <-c for _, v := range tweets.Results { fmt.Printf("%v:%v\n", v.Username, v.Text) } } func main() { c := make(chan *twitterResult) go retrieveTweets(c) for { displayTweets(c) } }
The objective is to write unit tests for this code, focusing on testing the HTTP requests made to retrieve tweets from Twitter's search API.
Solution Using httptest
The httptest package offers two types of tests: response tests and server tests. For this scenario, server tests are more suitable. Here's how to proceed:
func TestRetrieveTweets(t *testing.T){ ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprintln(w, `{"fake twitter json string"}`) })) defer ts.Close()
This code creates a test server that responds to HTTP requests with a predefined JSON response.
twitterUrl = ts.URL
In the original code, the twitterUrl variable is modified to point to the test server's URL instead of the actual Twitter API endpoint.
c := make(chan *twitterResult)
A channel is used to communicate between the test goroutine and the main goroutine in the original code.
go retrieveTweets(c)
This goroutine starts the process of retrieving tweets from the test server.
tweet := <-c if tweet != expected1 { t.Fail() } tweet = <-c if tweet != expected2 { t.Fail() }
The test goroutine receives tweets from the channel and checks if they match the expected results.
Further Considerations
It's worth noting that the test is not verifying the content of the HTTP response. For a more thorough test, it would be necessary to compare the actual response with the expected response. Additionally, the test server should return a more realistic response structure to accurately simulate the actual Twitter API.
The above is the detailed content of How to Unit Test HTTP Calls in Go using the `httptest` Package?. For more information, please follow other related articles on the PHP Chinese website!