gofight

package module
v2.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2024 License: MIT Imports: 12 Imported by: 1

README

Gofight

GoDoc Run Tests 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)
    })
}

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.

Documentation

Overview

Package gofight offers simple API http handler testing for Golang framework.

Details about the gofight project are found in github page:

https://github.com/appleboy/gofight

Installation:

$ go get -u github.com/appleboy/gofight

Set Header: You can add custom header via SetHeader func.

SetHeader(gofight.H{
  "X-Version": version,
})

Set Cookie: You can add custom cookie via SetCookie func.

SetCookie(gofight.H{
  "foo": "bar",
})

Set query string: Using SetQuery to generate query string data.

SetQuery(gofight.H{
  "a": "1",
  "b": "2",
})

POST FORM Data: Using SetForm to generate form data.

SetForm(gofight.H{
  "a": "1",
  "b": "2",
})

POST JSON Data: Using SetJSON to generate json data.

SetJSON(gofight.H{
  "a": "1",
  "b": "2",
})

POST RAW Data: Using SetBody to generate raw data.

SetBody("a=1&b=1")

For more details, see the documentation and example.

Index

Constants

View Source
const (
	Version         = "1.0"
	UserAgent       = "User-Agent"
	ContentType     = "Content-Type"
	ApplicationJSON = "application/json"
	ApplicationForm = "application/x-www-form-urlencoded"
)

Media types

Variables

This section is empty.

Functions

This section is empty.

Types

type D

type D map[string]interface{}

D is HTTP Data Type

type H

type H map[string]string

H is HTTP Header Type

type HTTPRequest

type HTTPRequest struct {
	*http.Request
}

HTTPRequest is a wrapper around the standard http.Request. It embeds the http.Request struct, allowing you to use all the methods and fields of http.Request while also providing the ability to extend its functionality with additional methods or fields if needed.

type HTTPResponse

type HTTPResponse struct {
	*httptest.ResponseRecorder
}

HTTPResponse wraps the httptest.ResponseRecorder to provide additional functionality or to simplify the response handling in tests.

type RequestConfig

type RequestConfig struct {
	Method      string
	Path        string
	Body        string
	Headers     H
	Cookies     H
	Debug       bool
	ContentType string
	Context     context.Context
}

RequestConfig provide user input request structure

func New

func New() *RequestConfig

New supply initial structure

func (*RequestConfig) DELETE

func (rc *RequestConfig) DELETE(path string) *RequestConfig

DELETE is request method.

func (*RequestConfig) GET

func (rc *RequestConfig) GET(path string) *RequestConfig

GET is request method.

func (*RequestConfig) HEAD

func (rc *RequestConfig) HEAD(path string) *RequestConfig

HEAD is request method.

func (*RequestConfig) OPTIONS

func (rc *RequestConfig) OPTIONS(path string) *RequestConfig

OPTIONS is request method.

func (*RequestConfig) PATCH

func (rc *RequestConfig) PATCH(path string) *RequestConfig

PATCH is request method.

func (*RequestConfig) POST

func (rc *RequestConfig) POST(path string) *RequestConfig

POST is request method.

func (*RequestConfig) PUT

func (rc *RequestConfig) PUT(path string) *RequestConfig

PUT is request method.

func (*RequestConfig) Run

func (rc *RequestConfig) Run(r http.Handler, response ResponseFunc)

Run executes the HTTP request using the provided http.Handler and processes the response using the given ResponseFunc. It initializes the test request and response writer, serves the HTTP request, and then passes the HTTP response and request to the response function.

Parameters:

  • r: The http.Handler that will handle the HTTP request.
  • response: A function that processes the HTTP response and request.

func (*RequestConfig) SetBody

func (rc *RequestConfig) SetBody(body string) *RequestConfig

SetBody supply raw body.

func (*RequestConfig) SetContext added in v2.2.0

func (rc *RequestConfig) SetContext(ctx context.Context) *RequestConfig

SetContext sets the context for the RequestConfig. This allows the request to be aware of deadlines, cancellation signals, and other request-scoped values. It returns the updated RequestConfig instance.

Parameters:

ctx - the context to be set for the RequestConfig

Returns:

*RequestConfig - the updated RequestConfig instance with the new context

func (*RequestConfig) SetCookie

func (rc *RequestConfig) SetCookie(cookies H) *RequestConfig

SetCookie supply cookies what you defined.

func (*RequestConfig) SetDebug

func (rc *RequestConfig) SetDebug(enable bool) *RequestConfig

SetDebug supply enable debug mode.

func (*RequestConfig) SetFileFromPath

func (rc *RequestConfig) SetFileFromPath(uploads []UploadFile, params ...H) *RequestConfig

SetFileFromPath upload new file.

func (*RequestConfig) SetForm

func (rc *RequestConfig) SetForm(body H) *RequestConfig

SetForm supply form body.

func (*RequestConfig) SetHeader

func (rc *RequestConfig) SetHeader(headers H) *RequestConfig

SetHeader supply http header what you defined.

func (*RequestConfig) SetJSON

func (rc *RequestConfig) SetJSON(body D) *RequestConfig

SetJSON supply JSON body.

func (*RequestConfig) SetJSONInterface

func (rc *RequestConfig) SetJSONInterface(body interface{}) *RequestConfig

SetJSONInterface supply JSON body

func (*RequestConfig) SetPath added in v2.2.0

func (rc *RequestConfig) SetPath(str string) *RequestConfig

SetPath supply new request path to deal with path variable request ex. /reqpath/:book/:apple , usage: r.POST("/reqpath/").SetPath("book1/apple2")...

func (*RequestConfig) SetQuery

func (rc *RequestConfig) SetQuery(query H) *RequestConfig

SetQuery supply query string.

func (*RequestConfig) SetQueryD added in v2.2.0

func (rc *RequestConfig) SetQueryD(query D) *RequestConfig

SetQueryD supply query string, support query using string array input. ex. /reqpath/?Ids[]=E&Ids[]=M usage: IDArray:=[]string{"E","M"} r.GET("reqpath").SetQueryD(gofight.D{`Ids[]`: IDArray})

type ResponseFunc

type ResponseFunc func(HTTPResponse, HTTPRequest)

ResponseFunc is a type alias for a function that takes an HTTPResponse and an HTTPRequest as parameters. It is used to define a callback function that can handle or process HTTP responses and requests.

type UploadFile

type UploadFile struct {
	Path    string
	Name    string
	Content []byte
}

UploadFile for upload file struct

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL