appleboy / gofight

Testing API Handler written in Golang.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Gofight

GoDoc Build Status Go Report Card codebeat badge codecov Sourcegraph

API Handler Testing for Golang Web framework.

Support Framework

Install

Download this package.

$ go get github.com/appleboy/gofight/v2

To import this package, add the following line to your code:

import "github.com/appleboy/gofight/v2"

Usage

The following is basic testing example.

Main Program:

package main

import (
	"io"
	"net/http"
)

func BasicHelloHandler(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello World")
}

func BasicEngine() http.Handler {
	mux := http.NewServeMux()
	mux.HandleFunc("/", BasicHelloHandler)

	return mux
}

Testing:

package main

import (
	"net/http"
	"testing"

	"github.com/appleboy/gofight/v2"
	"github.com/stretchr/testify/assert"
)

func TestBasicHelloWorld(t *testing.T) {
	r := gofight.New()

	r.GET("/").
		// turn on the debug mode.
		SetDebug(true).
		Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {

			assert.Equal(t, "Hello World", r.Body.String())
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

Set Header

You can add custom header via SetHeader func.

func TestBasicHelloWorld(t *testing.T) {
	r := gofight.New()
	version := "0.0.1"

	r.GET("/").
		// turn on the debug mode.
		SetDebug(true).
		SetHeader(gofight.H{
			"X-Version": version,
		}).
		Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {

			assert.Equal(t, version, rq.Header.Get("X-Version"))
			assert.Equal(t, "Hello World", r.Body.String())
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

POST FORM Data

Using SetForm to generate form data.

func TestPostFormData(t *testing.T) {
	r := gofight.New()

	r.POST("/form").
		SetForm(gofight.H{
			"a": "1",
			"b": "2",
		}).
		Run(BasicEngine(), func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			a, _ := jsonparser.GetString(data, "a")
			b, _ := jsonparser.GetString(data, "b")

			assert.Equal(t, "1", a)
			assert.Equal(t, "2", b)
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

POST JSON Data

Using SetJSON to generate JSON data.

func TestPostJSONData(t *testing.T) {
	r := gofight.New()

	r.POST("/json").
		SetJSON(gofight.D{
			"a": 1,
			"b": 2,
		}).
		Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			a, _ := jsonparser.GetInt(data, "a")
			b, _ := jsonparser.GetInt(data, "b")

			assert.Equal(t, 1, int(a))
			assert.Equal(t, 2, int(b))
			assert.Equal(t, http.StatusOK, r.Code)
			assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
		})
}

POST RAW Data

Using SetBody to generate raw data.

func TestPostRawData(t *testing.T) {
	r := gofight.New()

	r.POST("/raw").
		SetBody("a=1&b=1").
		Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			a, _ := jsonparser.GetString(data, "a")
			b, _ := jsonparser.GetString(data, "b")

			assert.Equal(t, "1", a)
			assert.Equal(t, "2", b)
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

Set Query String

Using SetQuery to generate raw data.

func TestQueryString(t *testing.T) {
	r := gofight.New()

	r.GET("/hello").
		SetQuery(gofight.H{
			"a": "1",
			"b": "2",
		}).
		Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

or append exist query parameter.

func TestQueryString(t *testing.T) {
	r := gofight.New()

	r.GET("/hello?foo=bar").
		SetQuery(gofight.H{
			"a": "1",
			"b": "2",
		}).
		Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
			assert.Equal(t, http.StatusOK, r.Code)
		})
}

Set Cookie String

Using SetCookie to generate raw data.

func TestQueryString(t *testing.T) {
	r := gofight.New()

	r.GET("/hello").
		SetCookie(gofight.H{
			"foo": "bar",
		}).
		Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {
			assert.Equal(t, http.StatusOK, r.Code)
			assert.Equal(t, "foo=bar", rq.Header.Get("cookie"))
		})
}

Set JSON Struct

type User struct {
	// Username user name
	Username string `json:"username"`
	// Password account password
	Password string `json:"password"`
}

func TestSetJSONInterface(t *testing.T) {
	r := New()

	r.POST("/user").
		SetJSONInterface(User{
			Username: "foo",
			Password: "bar",
		}).
		Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			username := gjson.GetBytes(data, "username")
			password := gjson.GetBytes(data, "password")

			assert.Equal(t, "foo", username.String())
			assert.Equal(t, "bar", password.String())
			assert.Equal(t, http.StatusOK, r.Code)
			assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
		})
}

Upload multiple file with absolute path and parameter

The following is route using gin

func gintFileUploadHandler(c *gin.Context) {
	ip := c.ClientIP()
	hello, err := c.FormFile("hello")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": err.Error(),
		})
		return
	}

	helloFile, _ := hello.Open()
	helloBytes := make([]byte, 6)
	helloFile.Read(helloBytes)

	world, err := c.FormFile("world")
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"error": err.Error(),
		})
		return
	}

	worldFile, _ := world.Open()
	worldBytes := make([]byte, 6)
	worldFile.Read(worldBytes)

	foo := c.PostForm("foo")
	bar := c.PostForm("bar")
	c.JSON(http.StatusOK, gin.H{
		"hello":		 hello.Filename,
		"world":		 world.Filename,
		"foo":			 foo,
		"bar":			 bar,
		"ip":				ip,
		"helloSize": string(helloBytes),
		"worldSize": string(worldBytes),
	})
}

Write the testing:

func TestUploadFile(t *testing.T) {
	r := New()

	r.POST("/upload").
		SetDebug(true).
		SetFileFromPath([]UploadFile{
			{
				Path: "./testdata/hello.txt",
				Name: "hello",
			},
			{
				Path: "./testdata/world.txt",
				Name: "world",
			},
		}, H{
			"foo": "bar",
			"bar": "foo",
		}).
		Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			hello := gjson.GetBytes(data, "hello")
			world := gjson.GetBytes(data, "world")
			foo := gjson.GetBytes(data, "foo")
			bar := gjson.GetBytes(data, "bar")
			ip := gjson.GetBytes(data, "ip")
			helloSize := gjson.GetBytes(data, "helloSize")
			worldSize := gjson.GetBytes(data, "worldSize")

			assert.Equal(t, "world\n", helloSize.String())
			assert.Equal(t, "hello\n", worldSize.String())
			assert.Equal(t, "hello.txt", hello.String())
			assert.Equal(t, "world.txt", world.String())
			assert.Equal(t, "bar", foo.String())
			assert.Equal(t, "foo", bar.String())
			assert.Equal(t, "", ip.String())
			assert.Equal(t, http.StatusOK, r.Code)
			assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
		})
}

Upload multiple file with content []byte path and parameter

func TestUploadFileByContent(t *testing.T) {
	r := New()

	helloContent, err := ioutil.ReadFile("./testdata/hello.txt")
	if err != nil {
		log.Fatal(err)
	}

	worldContent, err := ioutil.ReadFile("./testdata/world.txt")
	if err != nil {
		log.Fatal(err)
	}

	r.POST("/upload").
		SetDebug(true).
		SetFileFromPath([]UploadFile{
			{
				Path:		"hello.txt",
				Name:		"hello",
				Content: helloContent,
			},
			{
				Path:		"world.txt",
				Name:		"world",
				Content: worldContent,
			},
		}, H{
			"foo": "bar",
			"bar": "foo",
		}).
		Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {
			data := []byte(r.Body.String())

			hello := gjson.GetBytes(data, "hello")
			world := gjson.GetBytes(data, "world")
			foo := gjson.GetBytes(data, "foo")
			bar := gjson.GetBytes(data, "bar")
			ip := gjson.GetBytes(data, "ip")
			helloSize := gjson.GetBytes(data, "helloSize")
			worldSize := gjson.GetBytes(data, "worldSize")

			assert.Equal(t, "world\n", helloSize.String())
			assert.Equal(t, "hello\n", worldSize.String())
			assert.Equal(t, "hello.txt", hello.String())
			assert.Equal(t, "world.txt", world.String())
			assert.Equal(t, "bar", foo.String())
			assert.Equal(t, "foo", bar.String())
			assert.Equal(t, "", ip.String())
			assert.Equal(t, http.StatusOK, r.Code)
			assert.Equal(t, "application/json; charset=utf-8", r.HeaderMap.Get("Content-Type"))
		})
}

Example

License

Copyright 2019 Bo-Yi Wu @appleboy.

Licensed under the MIT License.

About

Testing API Handler written in Golang.

License:MIT License


Languages

Language:Go 92.7%Language:Makefile 7.3%