Skip to content

Instantly share code, notes, and snippets.

@hlhendy
Last active January 18, 2018 02:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save hlhendy/b50987d3006fc220e6d34068d42b7da8 to your computer and use it in GitHub Desktop.
Save hlhendy/b50987d3006fc220e6d34068d42b7da8 to your computer and use it in GitHub Desktop.
Women Who Go: Building a basic API in Go - Sample Tests
package main
import (
"net/http/httptest"
"testing"
"io/ioutil"
"strings"
)
/**
Below are some basic tests for the handlers used in this tutorial:
https://thenewstack.io/make-a-restful-json-api-go/
*/
func TestIndex(t *testing.T) {
tests := []struct {
description string
endpoint string
expectedCode int
expectedOutput string
}{
{
description: "success",
endpoint: "/",
expectedCode: 200,
expectedOutput: "Welcome!",
},
}
for _, tc := range tests {
req := httptest.NewRequest("GET", tc.endpoint, nil) // creating an http request
w := httptest.NewRecorder() // creating a response writer
Index(w, req) // calling the handler
if tc.expectedCode != w.Code {
t.Fatalf("Expected %s, but got %s", tc.expectedCode, w.Code)
}
b, err := ioutil.ReadAll(w.Body)
if err != nil {
t.Fatalf("Error getting response body: %+v", err)
}
output := strings.TrimSpace(string(b))
if tc.expectedOutput != output {
t.Fatalf("Expected %s, but got %s", tc.expectedOutput, output)
}
}
}
func TestTodoIndex(t *testing.T) {
tests := []struct {
description string
endpoint string
expectedCode int
expectedOutput string
}{
{
description: "success",
endpoint: "/todos",
expectedCode: 200,
expectedOutput: `[{"name":"Write presentation","completed":false,"due":"0001-01-01T00:00:00Z"},{"name":"Host meetup","completed":false,"due":"0001-01-01T00:00:00Z"}]`,
},
}
for _, tc := range tests {
req := httptest.NewRequest("GET", "/todos", nil)
w := httptest.NewRecorder()
TodoIndex(w, req)
if tc.expectedCode != w.Code {
t.Fatalf("Expected %s, but got %s", tc.expectedCode, w.Code)
}
b, err := ioutil.ReadAll(w.Body)
if err != nil {
t.Fatalf("Error getting response body: %+v", err)
}
output := strings.TrimSpace(string(b))
if tc.expectedOutput != output {
t.Fatalf("Expected %s, but got %s", tc.expectedOutput, output)
}
}
}
/*
Try adding error responses to your handler, and then
add test cases for those errors. For example, check the id length in TodoShow:
func TodoShow(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
todoId := vars["todoId"]
if len(todoId) < 4 {
http.Error(w, "INVALID_TODO_ID", 400)
return
}
fmt.Fprintln(w, "Todo show:", todoId)
}
Then you could add a test for TodoShow that looks like:
func TestTodoShow(t *testing.T) {
tests := []struct {
description string
endpoint string
id string
expectedCode int
expectedOutput string
}{
{
description: "failure - invalid id",
endpoint: "/todos/bad",
id: "bad",
expectedCode: 400,
expectedOutput: "INVALID_TODO_ID",
},
{
description: "success",
endpoint: "/todos/goodID",
id: "goodID",
expectedCode: 200,
expectedOutput: "Todo show: goodID",
},
}
for _, tc := range tests {
req := httptest.NewRequest("GET", tc.endpoint, nil)
w := httptest.NewRecorder()
// The reason we have to define a new router here
// is that there currently isn't a good way (that I found)
// to pass the route params to the handler in a unit test.
// See http://bit.ly/2DCdOtT for a few other options and more explanation.
NewRouter().ServeHTTP(w, req)
if tc.expectedCode != w.Code {
t.Fatalf("Expected %s, but got %s", tc.expectedCode, w.Code)
}
b, err := ioutil.ReadAll(w.Body)
if err != nil {
t.Fatalf("Error getting response body: %+v", err)
}
output := strings.TrimSpace(string(b))
if tc.expectedOutput != output {
t.Fatalf("Expected %s, but got %s", tc.expectedOutput, output)
}
}
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment