{"id":13413887,"url":"https://github.com/appleboy/gofight","last_synced_at":"2025-12-16T01:25:56.704Z","repository":{"id":48177647,"uuid":"54932530","full_name":"appleboy/gofight","owner":"appleboy","description":"Testing API Handler written in Golang.","archived":false,"fork":false,"pushed_at":"2025-04-16T23:27:56.000Z","size":1187,"stargazers_count":442,"open_issues_count":5,"forks_count":37,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-02T08:39:13.124Z","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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-03-29T00:13:21.000Z","updated_at":"2025-04-23T16:27:55.000Z","dependencies_parsed_at":"2022-09-09T14:20:43.493Z","dependency_job_id":"c9e37641-e33a-4e87-b673-1ea9f3667cf5","html_url":"https://github.com/appleboy/gofight","commit_stats":null,"previous_names":["appleboy/mocha"],"tags_count":9,"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":253517648,"owners_count":21920873,"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-30T20:01:52.001Z","updated_at":"2025-12-16T01:25:56.637Z","avatar_url":"https://github.com/appleboy.png","language":"Go","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","funding_links":[],"categories":["开源类库","Testing","Go","Open source library","测试","Template Engines","\u003cspan id=\"测试-testing\"\u003e测试 Testing\u003c/span\u003e","测试相关`测试库和测试数据集生成库`","Testing Frameworks","测试相关"],"sub_categories":["测试","Advanced Console UIs","Testing Frameworks","Test","HTTP客户端","HTTP Clients","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e","交流","查询语"],"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"}