{"id":13367078,"url":"https://github.com/appleboy/Gofight","last_synced_at":"2025-03-12T18:31:50.180Z","repository":{"id":48177647,"uuid":"54932530","full_name":"appleboy/gofight","owner":"appleboy","description":"Testing API Handler written in Golang.","archived":false,"fork":false,"pushed_at":"2021-06-27T15:34:44.000Z","size":1120,"stargazers_count":440,"open_issues_count":6,"forks_count":42,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-10-30T00:31:34.351Z","etag":null,"topics":["golang","testing-tools"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/appleboy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-29T00:13:21.000Z","updated_at":"2024-09-02T14:31:49.000Z","dependencies_parsed_at":"2022-09-09T14:20:43.493Z","dependency_job_id":null,"html_url":"https://github.com/appleboy/gofight","commit_stats":null,"previous_names":["appleboy/mocha"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgofight","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgofight/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgofight/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/appleboy%2Fgofight/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/appleboy","download_url":"https://codeload.github.com/appleboy/gofight/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243271406,"owners_count":20264451,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","testing-tools"],"created_at":"2024-07-30T00:01:38.028Z","updated_at":"2025-03-12T18:31:50.174Z","avatar_url":"https://github.com/appleboy.png","language":"Go","funding_links":[],"categories":["测试","測試"],"sub_categories":["高级控制台界面","高級控制台界面"],"readme":"# Gofight\n\n[![GoDoc](https://godoc.org/github.com/appleboy/gofight?status.svg)](https://godoc.org/github.com/appleboy/gofight)\n[![Run Tests](https://github.com/appleboy/gofight/actions/workflows/go.yml/badge.svg)](https://github.com/appleboy/gofight/actions/workflows/go.yml)\n[![Go Report Card](https://goreportcard.com/badge/github.com/appleboy/gofight)](https://goreportcard.com/report/github.com/appleboy/gofight)\n[![codebeat badge](https://codebeat.co/badges/4d8b58ae-67ec-469e-bde6-be3dd336b30d)](https://codebeat.co/projects/github-com-appleboy-gofight)\n[![codecov](https://codecov.io/gh/appleboy/gofight/branch/master/graph/badge.svg)](https://codecov.io/gh/appleboy/gofight)\n[![Sourcegraph](https://sourcegraph.com/github.com/appleboy/gofight/-/badge.svg)](https://sourcegraph.com/github.com/appleboy/gofight?badge)\n\nAPI Handler Testing for Golang Web framework.\n\n## Support Framework\n\n* [x] [Http Handler](https://golang.org/pkg/net/http/) Golang package http provides HTTP client and server implementations.\n* [x] [Gin](https://github.com/gin-gonic/gin)\n* [x] [Echo](https://github.com/labstack/echo) support [v3.0.0](https://github.com/labstack/echo/releases/tag/v3.0.0) up\n* [x] [Mux](https://github.com/gorilla/mux)\n\n## Install\n\nDownload this package.\n\n```bash\ngo get github.com/appleboy/gofight/v2\n```\n\nTo import this package, add the following line to your code:\n\n```go\nimport \"github.com/appleboy/gofight/v2\"\n```\n\n## Usage\n\nThe following is basic testing example.\n\nMain Program:\n\n```go\npackage main\n\nimport (\n  \"io\"\n  \"net/http\"\n)\n\nfunc BasicHelloHandler(w http.ResponseWriter, r *http.Request) {\n  io.WriteString(w, \"Hello World\")\n}\n\nfunc BasicEngine() http.Handler {\n  mux := http.NewServeMux()\n  mux.HandleFunc(\"/\", BasicHelloHandler)\n\n  return mux\n}\n```\n\nTesting:\n\n```go\npackage main\n\nimport (\n  \"net/http\"\n  \"testing\"\n\n  \"github.com/appleboy/gofight/v2\"\n  \"github.com/stretchr/testify/assert\"\n)\n\nfunc TestBasicHelloWorld(t *testing.T) {\n  r := gofight.New()\n\n  r.GET(\"/\").\n    // turn on the debug mode.\n    SetDebug(true).\n    Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {\n\n      assert.Equal(t, \"Hello World\", r.Body.String())\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\n### Set Header\n\nYou can add custom header via `SetHeader` func.\n\n```go\nfunc TestBasicHelloWorld(t *testing.T) {\n  r := gofight.New()\n  version := \"0.0.1\"\n\n  r.GET(\"/\").\n    // turn on the debug mode.\n    SetDebug(true).\n    SetHeader(gofight.H{\n      \"X-Version\": version,\n    }).\n    Run(BasicEngine(), func(r gofight.HTTPResponse, rq gofight.HTTPRequest) {\n\n      assert.Equal(t, version, rq.Header.Get(\"X-Version\"))\n      assert.Equal(t, \"Hello World\", r.Body.String())\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\n### POST FORM Data\n\nUsing `SetForm` to generate form data.\n\n```go\nfunc TestPostFormData(t *testing.T) {\n  r := gofight.New()\n\n  r.POST(\"/form\").\n    SetForm(gofight.H{\n      \"a\": \"1\",\n      \"b\": \"2\",\n    }).\n    Run(BasicEngine(), func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      a, _ := jsonparser.GetString(data, \"a\")\n      b, _ := jsonparser.GetString(data, \"b\")\n\n      assert.Equal(t, \"1\", a)\n      assert.Equal(t, \"2\", b)\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\n### POST JSON Data\n\nUsing `SetJSON` to generate JSON data.\n\n```go\nfunc TestPostJSONData(t *testing.T) {\n  r := gofight.New()\n\n  r.POST(\"/json\").\n    SetJSON(gofight.D{\n      \"a\": 1,\n      \"b\": 2,\n    }).\n    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      a, _ := jsonparser.GetInt(data, \"a\")\n      b, _ := jsonparser.GetInt(data, \"b\")\n\n      assert.Equal(t, 1, int(a))\n      assert.Equal(t, 2, int(b))\n      assert.Equal(t, http.StatusOK, r.Code)\n      assert.Equal(t, \"application/json; charset=utf-8\", r.HeaderMap.Get(\"Content-Type\"))\n    })\n}\n```\n\n### POST RAW Data\n\nUsing `SetBody` to generate raw data.\n\n```go\nfunc TestPostRawData(t *testing.T) {\n  r := gofight.New()\n\n  r.POST(\"/raw\").\n    SetBody(\"a=1\u0026b=1\").\n    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      a, _ := jsonparser.GetString(data, \"a\")\n      b, _ := jsonparser.GetString(data, \"b\")\n\n      assert.Equal(t, \"1\", a)\n      assert.Equal(t, \"2\", b)\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\n### Set Query String\n\nUsing `SetQuery` to generate raw data.\n\n```go\nfunc TestQueryString(t *testing.T) {\n  r := gofight.New()\n\n  r.GET(\"/hello\").\n    SetQuery(gofight.H{\n      \"a\": \"1\",\n      \"b\": \"2\",\n    }).\n    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\nor append exist query parameter.\n\n```go\nfunc TestQueryString(t *testing.T) {\n  r := gofight.New()\n\n  r.GET(\"/hello?foo=bar\").\n    SetQuery(gofight.H{\n      \"a\": \"1\",\n      \"b\": \"2\",\n    }).\n    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {\n      assert.Equal(t, http.StatusOK, r.Code)\n    })\n}\n```\n\n### Set Cookie String\n\nUsing `SetCookie` to generate raw data.\n\n```go\nfunc TestQueryString(t *testing.T) {\n  r := gofight.New()\n\n  r.GET(\"/hello\").\n    SetCookie(gofight.H{\n      \"foo\": \"bar\",\n    }).\n    Run(BasicEngine, func(r HTTPResponse, rq HTTPRequest) {\n      assert.Equal(t, http.StatusOK, r.Code)\n      assert.Equal(t, \"foo=bar\", rq.Header.Get(\"cookie\"))\n    })\n}\n```\n\n### Set JSON Struct\n\n```go\ntype User struct {\n  // Username user name\n  Username string `json:\"username\"`\n  // Password account password\n  Password string `json:\"password\"`\n}\n\nfunc TestSetJSONInterface(t *testing.T) {\n  r := New()\n\n  r.POST(\"/user\").\n    SetJSONInterface(User{\n      Username: \"foo\",\n      Password: \"bar\",\n    }).\n    Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      username := gjson.GetBytes(data, \"username\")\n      password := gjson.GetBytes(data, \"password\")\n\n      assert.Equal(t, \"foo\", username.String())\n      assert.Equal(t, \"bar\", password.String())\n      assert.Equal(t, http.StatusOK, r.Code)\n      assert.Equal(t, \"application/json; charset=utf-8\", r.HeaderMap.Get(\"Content-Type\"))\n    })\n}\n```\n\n### Upload multiple file with absolute path and parameter\n\nThe following is route using gin\n\n```go\nfunc gintFileUploadHandler(c *gin.Context) {\n  ip := c.ClientIP()\n  hello, err := c.FormFile(\"hello\")\n  if err != nil {\n    c.JSON(http.StatusBadRequest, gin.H{\n      \"error\": err.Error(),\n    })\n    return\n  }\n\n  helloFile, _ := hello.Open()\n  helloBytes := make([]byte, 6)\n  helloFile.Read(helloBytes)\n\n  world, err := c.FormFile(\"world\")\n  if err != nil {\n    c.JSON(http.StatusBadRequest, gin.H{\n      \"error\": err.Error(),\n    })\n    return\n  }\n\n  worldFile, _ := world.Open()\n  worldBytes := make([]byte, 6)\n  worldFile.Read(worldBytes)\n\n  foo := c.PostForm(\"foo\")\n  bar := c.PostForm(\"bar\")\n  c.JSON(http.StatusOK, gin.H{\n    \"hello\":     hello.Filename,\n    \"world\":     world.Filename,\n    \"foo\":       foo,\n    \"bar\":       bar,\n    \"ip\":        ip,\n    \"helloSize\": string(helloBytes),\n    \"worldSize\": string(worldBytes),\n  })\n}\n```\n\nWrite the testing:\n\n```go\nfunc TestUploadFile(t *testing.T) {\n  r := New()\n\n  r.POST(\"/upload\").\n    SetDebug(true).\n    SetFileFromPath([]UploadFile{\n      {\n        Path: \"./testdata/hello.txt\",\n        Name: \"hello\",\n      },\n      {\n        Path: \"./testdata/world.txt\",\n        Name: \"world\",\n      },\n    }, H{\n      \"foo\": \"bar\",\n      \"bar\": \"foo\",\n    }).\n    Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      hello := gjson.GetBytes(data, \"hello\")\n      world := gjson.GetBytes(data, \"world\")\n      foo := gjson.GetBytes(data, \"foo\")\n      bar := gjson.GetBytes(data, \"bar\")\n      ip := gjson.GetBytes(data, \"ip\")\n      helloSize := gjson.GetBytes(data, \"helloSize\")\n      worldSize := gjson.GetBytes(data, \"worldSize\")\n\n      assert.Equal(t, \"world\\n\", helloSize.String())\n      assert.Equal(t, \"hello\\n\", worldSize.String())\n      assert.Equal(t, \"hello.txt\", hello.String())\n      assert.Equal(t, \"world.txt\", world.String())\n      assert.Equal(t, \"bar\", foo.String())\n      assert.Equal(t, \"foo\", bar.String())\n      assert.Equal(t, \"\", ip.String())\n      assert.Equal(t, http.StatusOK, r.Code)\n      assert.Equal(t, \"application/json; charset=utf-8\", r.HeaderMap.Get(\"Content-Type\"))\n    })\n}\n```\n\n### Upload multiple file with content `[]byte` path and parameter\n\n```go\nfunc TestUploadFileByContent(t *testing.T) {\n  r := New()\n\n  helloContent, err := ioutil.ReadFile(\"./testdata/hello.txt\")\n  if err != nil {\n    log.Fatal(err)\n  }\n\n  worldContent, err := ioutil.ReadFile(\"./testdata/world.txt\")\n  if err != nil {\n    log.Fatal(err)\n  }\n\n  r.POST(\"/upload\").\n    SetDebug(true).\n    SetFileFromPath([]UploadFile{\n      {\n        Path:    \"hello.txt\",\n        Name:    \"hello\",\n        Content: helloContent,\n      },\n      {\n        Path:    \"world.txt\",\n        Name:    \"world\",\n        Content: worldContent,\n      },\n    }, H{\n      \"foo\": \"bar\",\n      \"bar\": \"foo\",\n    }).\n    Run(framework.GinEngine(), func(r HTTPResponse, rq HTTPRequest) {\n      data := []byte(r.Body.String())\n\n      hello := gjson.GetBytes(data, \"hello\")\n      world := gjson.GetBytes(data, \"world\")\n      foo := gjson.GetBytes(data, \"foo\")\n      bar := gjson.GetBytes(data, \"bar\")\n      ip := gjson.GetBytes(data, \"ip\")\n      helloSize := gjson.GetBytes(data, \"helloSize\")\n      worldSize := gjson.GetBytes(data, \"worldSize\")\n\n      assert.Equal(t, \"world\\n\", helloSize.String())\n      assert.Equal(t, \"hello\\n\", worldSize.String())\n      assert.Equal(t, \"hello.txt\", hello.String())\n      assert.Equal(t, \"world.txt\", world.String())\n      assert.Equal(t, \"bar\", foo.String())\n      assert.Equal(t, \"foo\", bar.String())\n      assert.Equal(t, \"\", ip.String())\n      assert.Equal(t, http.StatusOK, r.Code)\n      assert.Equal(t, \"application/json; charset=utf-8\", r.HeaderMap.Get(\"Content-Type\"))\n    })\n}\n```\n\n## Example\n\n* Basic HTTP Router: [example](./_example/basic)\n* Gin Framework: [example](./_example/gin)\n* Echo Framework: [example](./_example/echo)\n* Mux Framework: [example](./_example/mux)\n\n## License\n\nCopyright 2019 Bo-Yi Wu [@appleboy](https://twitter.com/appleboy).\n\nLicensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2FGofight","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fappleboy%2FGofight","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fappleboy%2FGofight/lists"}