{"id":13413897,"url":"https://github.com/gavv/httpexpect","last_synced_at":"2025-05-12T13:13:48.688Z","repository":{"id":8247905,"uuid":"57400412","full_name":"gavv/httpexpect","owner":"gavv","description":"End-to-end HTTP and REST API testing for Go.","archived":false,"fork":false,"pushed_at":"2025-04-16T19:52:29.000Z","size":2018,"stargazers_count":2637,"open_issues_count":17,"forks_count":242,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-05-11T01:35:21.840Z","etag":null,"topics":["assertions","http","json","rest","testing","websocket"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/gavv/httpexpect/v2","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/gavv.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"buy_me_a_coffee":"gavv","liberapay":"gavv"}},"created_at":"2016-04-29T17:05:20.000Z","updated_at":"2025-05-10T06:59:01.000Z","dependencies_parsed_at":"2023-12-29T08:34:20.966Z","dependency_job_id":"e5de424a-24e7-4d4a-bd9f-c79915fb0790","html_url":"https://github.com/gavv/httpexpect","commit_stats":{"total_commits":906,"total_committers":79,"mean_commits":"11.468354430379748","dds":"0.22737306843267113","last_synced_commit":"07a4dbe680a31629b43830c7126669d4be2332e2"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gavv%2Fhttpexpect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gavv%2Fhttpexpect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gavv%2Fhttpexpect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gavv%2Fhttpexpect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gavv","download_url":"https://codeload.github.com/gavv/httpexpect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253660846,"owners_count":21943823,"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":["assertions","http","json","rest","testing","websocket"],"created_at":"2024-07-30T20:01:52.258Z","updated_at":"2025-05-12T13:13:48.652Z","avatar_url":"https://github.com/gavv.png","language":"Go","readme":"![](_images/logo.png)\n\n# httpexpect [![GoDev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go\u0026logoColor=white)](https://pkg.go.dev/github.com/gavv/httpexpect/v2) [![Build](https://github.com/gavv/httpexpect/workflows/build/badge.svg)](https://github.com/gavv/httpexpect/actions) [![Coveralls](https://coveralls.io/repos/github/gavv/httpexpect/badge.svg?branch=master)](https://coveralls.io/github/gavv/httpexpect?branch=master) [![GitHub release](https://img.shields.io/github/tag/gavv/httpexpect.svg)](https://github.com/gavv/httpexpect/releases) [![Discord](https://img.shields.io/discord/1047473005900615780?logo=discord\u0026label=discord\u0026color=blueviolet\u0026logoColor=white)](https://discord.gg/5SCPCuCWA9)\n\nConcise, declarative, and easy to use end-to-end HTTP and REST API testing for Go (golang).\n\nBasically, httpexpect is a set of chainable *builders* for HTTP requests and *assertions* for HTTP responses and payload, on top of net/http and several utility packages.\n\nWorkflow:\n\n* Incrementally build HTTP requests.\n* Inspect HTTP responses.\n* Inspect response payload recursively.\n\n## Features\n\n##### Request builder\n\n* URL path construction, with simple string interpolation provided by [`go-interpol`](https://github.com/imkira/go-interpol) package.\n* URL query parameters (encoding using [`go-querystring`](https://github.com/google/go-querystring) package).\n* Headers, cookies, payload: JSON, urlencoded or multipart forms (encoding using [`form`](https://github.com/ajg/form) package), plain text.\n* Custom reusable [request builders](#reusable-builders) and [request transformers](#request-transformers).\n\n##### Response assertions\n\n* Response status, predefined status ranges.\n* Headers, cookies, payload: JSON, JSONP, forms, text.\n* Round-trip time.\n* Custom reusable [response matchers](#reusable-matchers).\n\n##### Payload assertions\n\n* Type-specific assertions, supported types: object, array, string, number, boolean, null, datetime, duration, cookie.\n* Regular expressions.\n* Simple JSON queries (using subset of [JSONPath](http://goessner.net/articles/JsonPath/)), provided by [`jsonpath`](https://github.com/yalp/jsonpath) package.\n* [JSON Schema](http://json-schema.org/) validation, provided by [`gojsonschema`](https://github.com/xeipuuv/gojsonschema) package.\n\n##### WebSocket support (thanks to [@tyranron](https://github.com/tyranron))\n\n* Upgrade an HTTP connection to a WebSocket connection (we use [`gorilla/websocket`](https://github.com/gorilla/websocket) internally).\n* Interact with the WebSocket server.\n* Inspect WebSocket connection parameters and WebSocket messages.\n\n##### Pretty printing\n\n* Verbose error messages.\n* JSON diff is produced on failure using [`gojsondiff`](https://github.com/yudai/gojsondiff/) package.\n* Failures are reported using [`testify`](https://github.com/stretchr/testify/) (`assert` or `require` package) or standard `testing` package.\n* JSON values are pretty-printed using `encoding/json`, Go values are pretty-printed using [`litter`](https://github.com/sanity-io/litter).\n* Dumping requests and responses in various formats, using [`httputil`](https://golang.org/pkg/net/http/httputil/), [`http2curl`](https://github.com/moul/http2curl), or simple compact logger.\n* Printing stacktrace on failure in verbose or compact format.\n* Color support using [`fatih/color`](https://github.com/fatih/color).\n\n##### Tuning\n\n* Tests can communicate with server via real HTTP client or invoke `net/http` or [`fasthttp`](https://github.com/valyala/fasthttp/) handler directly.\n* User can provide custom HTTP client, WebSocket dialer, HTTP request factory (e.g. from the Google App Engine testing).\n* User can configure redirect and retry policies and timeouts.\n* User can configure formatting options (what parts to display, how to format numbers, etc.) or provide custom templates based on `text/template` engine.\n* Custom handlers may be provided for logging, printing requests and responses, handling succeeded and failed assertions.\n\n## Versioning\n\nThe versions are selected according to the [semantic versioning](https://semver.org/) scheme. Every new major version gets its own stable branch with a backwards compatibility promise. Releases are tagged from stable branches.\n\nChangelog file can be found here: [changelog](CHANGES.md).\n\nThe current stable branch is `v2`:\n\n```go\nimport \"github.com/gavv/httpexpect/v2\"\n```\n\n## Documentation\n\nDocumentation is available on [pkg.go.dev](https://pkg.go.dev/github.com/gavv/httpexpect/v2#section-documentation). It contains an overview and reference.\n\n## Community\n\nCommunity forum and Q\u0026A board is right on GitHub in [discussions tab](https://github.com/gavv/httpexpect/discussions).\n\nFor more interactive discussion, you can join [discord chat](https://discord.gg/5SCPCuCWA9).\n\n## Contributing\n\nFeel free to report bugs, suggest improvements, and send pull requests! Please add documentation and tests for new features.\n\nThis project highly depends on contributors. Thank you all for your amazing work!\n\nIf you would like to submit code, see [HACKING.md](HACKING.md).\n\n## Donating\n\nIf you would like to support my open-source work, you can do it here:\n\n* [Liberapay](https://liberapay.com/gavv)\n* [PayPal](https://www.paypal.com/paypalme/victorgaydov)\n\nThanks!\n\n## Examples\n\nSee [`_examples`](_examples) directory for complete standalone examples.\n\n* [`fruits_test.go`](_examples/fruits_test.go)\n\n    Testing a simple CRUD server made with bare `net/http`.\n\n* [`iris_test.go`](_examples/iris_test.go)\n\n    Testing a server made with [`iris`](https://github.com/kataras/iris/) framework. Example includes JSON queries and validation, URL and form parameters, basic auth, sessions, and streaming. Tests invoke the `http.Handler` directly.\n\n* [`echo_test.go`](_examples/echo_test.go)\n\n    Testing a server with JWT authentication made with [`echo`](https://github.com/labstack/echo/) framework. Tests use either HTTP client or invoke the `http.Handler` directly.\n\n* [`gin_test.go`](_examples/gin_test.go)\n\n    Testing a server utilizing the [`gin`](https://github.com/gin-gonic/gin) web framework. Tests invoke the `http.Handler` directly.\n\n* [`fasthttp_test.go`](_examples/fasthttp_test.go)\n\n    Testing a server made with [`fasthttp`](https://github.com/valyala/fasthttp) package. Tests invoke the `fasthttp.RequestHandler` directly.\n\n* [`websocket_test.go`](_examples/websocket_test.go)\n\n    Testing a WebSocket server based on [`gorilla/websocket`](https://github.com/gorilla/websocket). Tests invoke the `http.Handler` or `fasthttp.RequestHandler` directly.\n\n* [`tls_test.go`](_examples/tls_test.go)\n\n  Testing a TLS server made with `net/http` and `crypto/tls`\n\n* [`oauth2_test.go`](_examples/oauth2_test.go)\n\n  Testing a OAuth2 server with [`oauth2`](https://github.com/go-oauth2/oauth2/).\n\n* [`gae_test.go`](_examples/gae_test.go)\n\n    Testing a server running under the [Google App Engine](https://en.wikipedia.org/wiki/Google_App_Engine).\n\n* [`formatter_test.go`](_examples/formatter_test.go)\n\n    Testing with custom formatter for assertion messages.\n\n## Quick start\n\n##### Hello, world!\n\n```go\npackage example\n\nimport (\n\t\"net/http\"\n\t\"net/http/httptest\"\n\t\"testing\"\n\n\t\"github.com/gavv/httpexpect/v2\"\n)\n\nfunc TestFruits(t *testing.T) {\n\t// create http.Handler\n\thandler := FruitsHandler()\n\n\t// run server using httptest\n\tserver := httptest.NewServer(handler)\n\tdefer server.Close()\n\n\t// create httpexpect instance\n\te := httpexpect.Default(t, server.URL)\n\n\t// is it working?\n\te.GET(\"/fruits\").\n\t\tExpect().\n\t\tStatus(http.StatusOK).JSON().Array().IsEmpty()\n}\n```\n\n##### JSON\n\n```go\norange := map[string]interface{}{\n\t\"weight\": 100,\n}\n\ne.PUT(\"/fruits/orange\").WithJSON(orange).\n\tExpect().\n\tStatus(http.StatusNoContent).NoContent()\n\ne.GET(\"/fruits/orange\").\n\tExpect().\n\tStatus(http.StatusOK).\n\tJSON().Object().ContainsKey(\"weight\").HasValue(\"weight\", 100)\n\napple := map[string]interface{}{\n\t\"colors\": []interface{}{\"green\", \"red\"},\n\t\"weight\": 200,\n}\n\ne.PUT(\"/fruits/apple\").WithJSON(apple).\n\tExpect().\n\tStatus(http.StatusNoContent).NoContent()\n\nobj := e.GET(\"/fruits/apple\").\n\tExpect().\n\tStatus(http.StatusOK).JSON().Object()\n\nobj.Keys().ContainsOnly(\"colors\", \"weight\")\n\nobj.Value(\"colors\").Array().ConsistsOf(\"green\", \"red\")\nobj.Value(\"colors\").Array().Value(0).String().IsEqual(\"green\")\nobj.Value(\"colors\").Array().Value(1).String().IsEqual(\"red\")\nobj.Value(\"colors\").Array().First().String().IsEqual(\"green\")\nobj.Value(\"colors\").Array().Last().String().IsEqual(\"red\")\n```\n\n##### JSON Schema and JSON Path\n\n```go\nschema := `{\n\t\"type\": \"array\",\n\t\"items\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t...\n\t\t\t\"private\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t}\n\t\t}\n\t}\n}`\n\nrepos := e.GET(\"/repos/octocat\").\n\tExpect().\n\tStatus(http.StatusOK).JSON()\n\n// validate JSON schema\nrepos.Schema(schema)\n\n// run JSONPath query and iterate results\nfor _, private := range repos.Path(\"$..private\").Array().Iter() {\n\tprivate.Boolean().IsFalse()\n}\n```\n\n##### JSON decoding\n\n```go\ntype User struct {\n\tName   string `json:\"name\"`\n\tAge    int    `json:\"age\"`\n\tGender string `json:\"gender\"`\n}\n\nvar user User\ne.GET(\"/user\").\n\tExpect().\n\tStatus(http.StatusOK).\n\tJSON().\n\tDecode(\u0026user)\n\t\nif user.Name != \"octocat\" {\n\tt.Fail()\n}\n```\n\n##### Forms\n\n```go\n// post form encoded from struct or map\ne.POST(\"/form\").WithForm(structOrMap).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// set individual fields\ne.POST(\"/form\").WithFormField(\"foo\", \"hello\").WithFormField(\"bar\", 123).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// multipart form\ne.POST(\"/form\").WithMultipart().\n\tWithFile(\"avatar\", \"./john.png\").WithFormField(\"username\", \"john\").\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### URL construction\n\n```go\n// construct path using ordered parameters\ne.GET(\"/repos/{user}/{repo}\", \"octocat\", \"hello-world\").\n\tExpect().\n\tStatus(http.StatusOK)\n\n// construct path using named parameters\ne.GET(\"/repos/{user}/{repo}\").\n\tWithPath(\"user\", \"octocat\").WithPath(\"repo\", \"hello-world\").\n\tExpect().\n\tStatus(http.StatusOK)\n\n// set query parameters\ne.GET(\"/repos/{user}\", \"octocat\").WithQuery(\"sort\", \"asc\").\n\tExpect().\n\tStatus(http.StatusOK)    // \"/repos/octocat?sort=asc\"\n```\n\n##### Headers\n\n```go\n// set If-Match\ne.POST(\"/users/john\").WithHeader(\"If-Match\", etag).WithJSON(john).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// check ETag\ne.GET(\"/users/john\").\n\tExpect().\n\tStatus(http.StatusOK).Header(\"ETag\").NotEmpty()\n\n// check Date\nt := time.Now()\n\ne.GET(\"/users/john\").\n\tExpect().\n\tStatus(http.StatusOK).Header(\"Date\").AsDateTime().InRange(t, time.Now())\n```\n\n##### Cookies\n\n```go\n// set cookie\nt := time.Now()\n\ne.POST(\"/users/john\").WithCookie(\"session\", sessionID).WithJSON(john).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// check cookies\nc := e.GET(\"/users/john\").\n\tExpect().\n\tStatus(http.StatusOK).Cookie(\"session\")\n\nc.Value().IsEqual(sessionID)\nc.Domain().IsEqual(\"example.com\")\nc.Path().IsEqual(\"/\")\nc.Expires().InRange(t, t.Add(time.Hour * 24))\n```\n\n##### Regular expressions\n\n```go\n// simple match\ne.GET(\"/users/john\").\n\tExpect().\n\tHeader(\"Location\").\n\tMatch(\"http://(.+)/users/(.+)\").Values(\"example.com\", \"john\")\n\n// check capture groups by index or name\nm := e.GET(\"/users/john\").\n\tExpect().\n\tHeader(\"Location\").Match(\"http://(?P\u003chost\u003e.+)/users/(?P\u003cuser\u003e.+)\")\n\nm.Submatch(0).IsEqual(\"http://example.com/users/john\")\nm.Submatch(1).IsEqual(\"example.com\")\nm.Submatch(2).IsEqual(\"john\")\n\nm.NamedSubmatch(\"host\").IsEqual(\"example.com\")\nm.NamedSubmatch(\"user\").IsEqual(\"john\")\n```\n\n##### Redirection support\n\n```go\ne.POST(\"/path\").\n\tWithRedirectPolicy(httpexpect.FollowAllRedirects).\n\tWithMaxRedirects(5).\n\tExpect().\n\tStatus(http.StatusOK)\n\ne.POST(\"/path\").\n\tWithRedirectPolicy(httpexpect.DontFollowRedirects).\n\tExpect().\n\tStatus(http.StatusPermanentRedirect)\n```\n\n##### Retry support\n\n```go\n// default retry policy\ne.POST(\"/path\").\n\tWithMaxRetries(5).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// custom built-in retry policy\ne.POST(\"/path\").\n\tWithMaxRetries(5).\n\tWithRetryPolicy(httpexpect.RetryAllErrors).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// custom retry delays\ne.POST(\"/path\").\n\tWithMaxRetries(5).\n\tWithRetryDelay(time.Second, time.Minute).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// custom user-defined retry policy\ne.POST(\"/path\").\n\tWithMaxRetries(5).\n\tWithRetryPolicyFunc(func(resp *http.Response, err error) bool {\n\t\treturn resp.StatusCode == http.StatusTeapot\n\t}).\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### Subdomains and per-request URL\n\n```go\ne.GET(\"/path\").WithURL(\"http://example.com\").\n\tExpect().\n\tStatus(http.StatusOK)\n\ne.GET(\"/path\").WithURL(\"http://subdomain.example.com\").\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### WebSocket support\n\n```go\nws := e.GET(\"/mysocket\").WithWebsocketUpgrade().\n\tExpect().\n\tStatus(http.StatusSwitchingProtocols).\n\tWebsocket()\ndefer ws.Disconnect()\n\nws.WriteText(\"some request\").\n\tExpect().\n\tTextMessage().Body().IsEqual(\"some response\")\n\nws.CloseWithText(\"bye\").\n\tExpect().\n\tCloseMessage().NoContent()\n```\n\n##### Reusable builders\n\n```go\ne := httpexpect.Default(t, \"http://example.com\")\n\nr := e.POST(\"/login\").WithForm(Login{\"ford\", \"betelgeuse7\"}).\n\tExpect().\n\tStatus(http.StatusOK).JSON().Object()\n\ntoken := r.Value(\"token\").String().Raw()\n\nauth := e.Builder(func (req *httpexpect.Request) {\n\treq.WithHeader(\"Authorization\", \"Bearer \"+token)\n})\n\nauth.GET(\"/restricted\").\n\tExpect().\n\tStatus(http.StatusOK)\n\ne.GET(\"/restricted\").\n\tExpect().\n\tStatus(http.StatusUnauthorized)\n```\n\n##### Reusable matchers\n\n```go\ne := httpexpect.Default(t, \"http://example.com\")\n\n// every response should have this header\nm := e.Matcher(func (resp *httpexpect.Response) {\n\tresp.Header(\"API-Version\").NotEmpty()\n})\n\nm.GET(\"/some-path\").\n\tExpect().\n\tStatus(http.StatusOK)\n\nm.GET(\"/bad-path\").\n\tExpect().\n\tStatus(http.StatusNotFound)\n```\n\n##### Request transformers\n\n```go\ne := httpexpect.Default(t, \"http://example.com\")\n\nmyTranform := func(r* http.Request) {\n\t// modify the underlying http.Request\n}\n\n// apply transformer to a single request\ne.POST(\"/some-path\").\n\tWithTransformer(myTranform).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// create a builder that applies transfromer to every request\nmyBuilder := e.Builder(func (req *httpexpect.Request) {\n\treq.WithTransformer(myTranform)\n})\n\nmyBuilder.POST(\"/some-path\").\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### Shared environment\n\n```go\ne := httpexpect.Default(t, \"http://example.com\")\n\nt.Run(\"/users\", func(t *testing.T) {\n\tobj := e.GET(\"/users\").\n\t\tExpect().\n\t\tStatus(http.StatusOK).JSON().Object()\n\n\t// store user id for next tests\n\tuserID := obj.Path(\"$.users[1].id\").String().Raw()\n\te.Env().Put(\"user1.id\", userID)\n})\n\nt.Run(\"/user/{userId}\", func(t *testing.T) {\n\t// read user id from previous tests\n\tuserID := e.Env().GetString(\"user1.id\")\n\n\te.GET(\"/user/{userId}\").\n\t\tWithPath(\"userId\", userID)\n\t\tExpect().\n\t\tStatus(http.StatusOK)\n})\n```\n\n##### Custom config\n\n```go\ne := httpexpect.WithConfig(httpexpect.Config{\n\t// include test name in failures (optional)\n\tTestName: t.Name(),\n\n\t// prepend this url to all requests\n\tBaseURL: \"http://example.com\",\n\n\t// use http.Client with a cookie jar and timeout\n\tClient: \u0026http.Client{\n\t\tJar:     httpexpect.NewCookieJar(),\n\t\tTimeout: time.Second * 30,\n\t},\n\n\t// use fatal failures\n\tReporter: httpexpect.NewRequireReporter(t),\n\n\t// print all requests and responses\n\tPrinters: []httpexpect.Printer{\n\t\thttpexpect.NewDebugPrinter(t, true),\n\t},\n})\n```\n\n##### Use HTTP handler directly\n\n```go\n// invoke http.Handler directly using httpexpect.Binder\nvar handler http.Handler = myHandler()\n\ne := httpexpect.WithConfig(httpexpect.Config{\n\t// prepend this url to all requests, required for cookies\n\t// to be handled correctly\n\tBaseURL: \"http://example.com\",\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tTransport: httpexpect.NewBinder(handler),\n\t\tJar:       httpexpect.NewCookieJar(),\n\t},\n})\n\n// invoke fasthttp.RequestHandler directly using httpexpect.FastBinder\nvar handler fasthttp.RequestHandler = myHandler()\n\ne := httpexpect.WithConfig(httpexpect.Config{\n\t// prepend this url to all requests, required for cookies\n\t// to be handled correctly\n\tBaseURL: \"http://example.com\",\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tTransport: httpexpect.NewFastBinder(handler),\n\t\tJar:       httpexpect.NewCookieJar(),\n\t},\n})\n```\n\n##### Per-request client or handler\n\n```go\ne := httpexpect.Default(t, server.URL)\n\nclient := \u0026http.Client{\n\tTransport: \u0026http.Transport{\n\t\tDisableCompression: true,\n\t},\n}\n\n// overwrite client\ne.GET(\"/path\").WithClient(client).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// construct client that invokes a handler directly and overwrite client\ne.GET(\"/path\").WithHandler(handler).\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### WebSocket dialer\n\n```go\n// invoke http.Handler directly using websocket.Dialer\nvar handler http.Handler = myHandler()\n\ne := httpexpect.WithConfig(httpexpect.Config{\n\tBaseURL:         \"http://example.com\",\n\tReporter:        httpexpect.NewAssertReporter(t),\n\tWebsocketDialer: httpexpect.NewWebsocketDialer(handler),\n})\n\n// invoke fasthttp.RequestHandler directly using websocket.Dialer\nvar handler fasthttp.RequestHandler = myHandler()\n\ne := httpexpect.WithConfig(httpexpect.Config{\n\tBaseURL:         \"http://example.com\",\n\tReporter:        httpexpect.NewAssertReporter(t),\n\tWebsocketDialer: httpexpect.NewFastWebsocketDialer(handler),\n})\n```\n\n##### Session support\n\n```go\n// cookie jar is used to store cookies from server\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tJar: httpexpect.NewCookieJar(), // used by default if Client is nil\n\t},\n})\n\n// cookies are disabled\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tJar: nil,\n\t},\n})\n```\n\n##### TLS support\n\n```go\n// use TLS with http.Transport\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tTransport: \u0026http.Transport{\n\t\t\tTLSClientConfig: \u0026tls.Config{\n\t\t\t\t// accept any certificate; for testing only!\n\t\t\t\tInsecureSkipVerify: true,\n\t\t\t},\n\t\t},\n\t},\n})\n\n// use TLS with http.Handler\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tTransport: \u0026httpexpect.Binder{\n\t\t\tHandler: myHandler,\n\t\t\tTLS:     \u0026tls.ConnectionState{},\n\t\t},\n\t},\n})\n```\n\n##### Proxy support\n\n```go\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tClient: \u0026http.Client{\n\t\tTransport: \u0026http.Transport{\n\t\t\tProxy: http.ProxyURL(\"http://proxy.example.com\"),\n\t\t},\n\t},\n})\n```\n\n##### Global timeout/cancellation\n\n```go\nhandler := FruitsHandler()\n\nserver := httptest.NewServer(handler)\ndefer server.Close()\n\nctx, cancel := context.WithCancel(context.Background())\n\ne := WithConfig(Config{\n\tBaseURL:  server.URL,\n\tReporter: httpexpect.NewAssertReporter(t),\n\tContext:  ctx,\n})\n\ngo func() {\n\ttime.Sleep(time.Duration(5)*time.Second)\n\tcancel()\n}()\n\ne.GET(\"/fruits\").\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### Per-request timeout/cancellation\n\n```go\n// per-request context\ne.GET(\"/fruits\").\n\tWithContext(context.TODO()).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// per-request timeout\ne.GET(\"/fruits\").\n\tWithTimeout(time.Duration(5)*time.Second).\n\tExpect().\n\tStatus(http.StatusOK)\n\n// timeout combined with retries (timeout applies to each try)\ne.POST(\"/fruits\").\n\tWithMaxRetries(5).\n\tWithTimeout(time.Duration(10)*time.Second).\n\tExpect().\n\tStatus(http.StatusOK)\n```\n\n##### Choosing failure reporter\n\n```go\n// default reporter, uses testify/assert\n// failures don't terminate test immediately, but mark test as failed\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n})\n\n// uses testify/require\n// failures terminate test immediately\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewRequireReporter(t),\n})\n\n// if you're using bare testing.T without testify\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: t,\n})\n\n// if you're using bare testing.T and want failures to terminate test immediately\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewFatalReporter(t),\n})\n\n// if you want fatal failures triggered from other goroutines\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewPanicReporter(t),\n})\n```\n\n##### Assigning names to requests\n\n```go\n// when the tests fails, assertion message will mention request name:\n//   request name: Get Fruits\ne.GET(\"/fruits\").\n    WithName(\"Get Fruits\")\n\tExpect().\n\tStatus(http.StatusOK).JSON().Array().IsEmpty()\n```\n\n##### Assigning aliases to values\n\n```go\n// when the tests fails, assertion path in the failure message is:\n//   assertion: Request(\"GET\").Expect().JSON().Array().IsEmpty()\ne.GET(\"/fruits\").\n\tExpect().\n\tStatus(http.StatusOK).JSON().Array().IsEmpty()\n\n// assign alias \"fruits\" to the Array variable\nfruits := e.GET(\"/fruits\").\n\tExpect().\n\tStatus(http.StatusOK).JSON().Array().Alias(\"fruits\")\n\n// assertion path in the failure message is now:\n//   assertion: fruits.IsEmpty()\nfruits.IsEmpty()\n```\n\n##### Printing requests and responses\n\n```go\n// print requests in short form, don't print responses\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tPrinters: []httpexpect.Printer{\n\t\thttpexpect.NewCompactPrinter(t),\n\t},\n})\n\n// print requests as curl commands that can be inserted into terminal\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tPrinters: []httpexpect.Printer{\n\t\thttpexpect.NewCurlPrinter(t),\n\t},\n})\n\n// print requests and responses in verbose form\n// also print all incoming and outgoing websocket messages\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter: httpexpect.NewAssertReporter(t),\n\tPrinters: []httpexpect.Printer{\n\t\thttpexpect.NewDebugPrinter(t, true),\n\t},\n})\n```\n\n##### Customize failure formatting\n\n```go\n// change formatting options\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter:  httpexpect.NewAssertReporter(t),\n\tFormatter: \u0026httpexpect.DefaultFormatter{\n\t\tDisablePaths: true,\n\t\tDisableDiffs: true,\n\t\tFloatFormat:  httpexpect.FloatFormatScientific,\n\t\tColorMode:    httpexpect.ColorModeNever,\n\t\tLineWidth:    80,\n\t},\n})\n\n// provide custom templates\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter:  httpexpect.NewAssertReporter(t),\n\tFormatter: \u0026httpexpect.DefaultFormatter{\n\t\tSuccessTemplate: \"...\",\n\t\tFailureTemplate: \"...\",\n\t\tTemplateFuncs:   template.FuncMap{ ... },\n\t},\n})\n\n// provide custom formatter\ne := httpexpect.WithConfig(httpexpect.Config{\n\tReporter:  httpexpect.NewAssertReporter(t),\n\tFormatter: \u0026MyFormatter{},\n})\n```\n\n##### Customize assertion handling\n\n```go\n// enable printing of succeeded assertions\ne := httpexpect.WithConfig(httpexpect.Config{\n\tAssertionHandler: \u0026httpexpect.DefaultAssertionHandler{\n\t\tFormatter: \u0026httpexpect.DefaultFormatter{},\n\t\tReporter:  httpexpect.NewAssertReporter(t),\n\t\tLogger:    t, // specify logger to enable printing of succeeded assertions\n\t},\n})\n\n// provide custom assertion handler\n// here you can implement custom handling of succeeded and failed assertions\n// this may be useful for integrating httpexpect with other testing libs\n// if desired, you can completely ignore builtin Formatter, Reporter, and Logger\ne := httpexpect.WithConfig(httpexpect.Config{\n\tAssertionHandler: \u0026MyAssertionHandler{},\n})\n```\n\n## Environment variables\n\nThe following environment variables are checked when `ColorModeAuto` is used:\n\n* `FORCE_COLOR` - if set to a positive integers, colors are enabled\n* `NO_COLOR` - if set to non-empty string, colors are disabled ([see also](https://no-color.org/))\n* `TERM` - if starts with `dumb`, colors are disabled\n\n## Similar packages\n\n* [`gorequest`](https://github.com/parnurzeal/gorequest)\n* [`apitest`](https://github.com/steinfletcher/apitest)\n* [`baloo`](https://github.com/h2non/baloo)\n* [`gofight`](https://github.com/appleboy/gofight)\n* [`go-hit`](https://github.com/Eun/go-hit)\n* [`frisby`](https://github.com/verdverm/frisby)\n* [`forest`](https://github.com/emicklei/forest)\n* [`restit`](https://github.com/go-restit/restit)\n\n## Authors\n\nList of contributors can be [found here](AUTHORS.md).\n\nIf your name is missing or you want to change its appearance, feel free to submit PR!\n\n## License\n\n[MIT](LICENSE)\n","funding_links":["https://buymeacoffee.com/gavv","https://liberapay.com/gavv","https://www.paypal.com/paypalme/victorgaydov"],"categories":["Template Engines","Testing","开源类库","Misc","Go","測試","Open source library","测试","websocket","Testing Frameworks","测试相关","测试相关`测试库和测试数据集生成库`","\u003cspan id=\"测试-testing\"\u003e测试 Testing\u003c/span\u003e"],"sub_categories":["Testing Frameworks","测试","高級控制台界面","Test","HTTP客户端","HTTP Clients","Advanced Console UIs","Misc","高级控制台界面","查询语","交流","\u003cspan id=\"高级控制台用户界面-advanced-console-uis\"\u003e高级控制台用户界面 Advanced Console UIs\u003c/span\u003e"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgavv%2Fhttpexpect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgavv%2Fhttpexpect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgavv%2Fhttpexpect/lists"}