Home >Backend Development >Golang >How to Unit Test HTTP Calls in Go using the `httptest` Package?

How to Unit Test HTTP Calls in Go using the `httptest` Package?

Susan Sarandon
Susan SarandonOriginal
2024-12-13 16:21:10567browse

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 &amp;twitterResult{} which returns *twitterResult
        err = json.Unmarshal(body, &amp;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:

  1. Create a Test Server:
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.

  1. Update the Original Code:
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.

  1. Create a Channel:
c := make(chan *twitterResult)

A channel is used to communicate between the test goroutine and the main goroutine in the original code.

  1. Start a Goroutine to Retrieve Tweets:
go retrieveTweets(c)

This goroutine starts the process of retrieving tweets from the test server.

  1. Receive Tweets:
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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn