- Notifications
You must be signed in to change notification settings - Fork3
htest is a http-test package
License
Hexilee/htest
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Test a Handler or a HandlerFunc
// example/basic_mock_client.gopackage myappimport ("io""net/http")funcNameHandler(w http.ResponseWriter,req*http.Request) {io.WriteString(w,`{"name": "hexi"}`)}
// example/basic_mock_client_test.gopackage myappimport ("testing""github.com/Hexilee/htest")funcTestNameHandlerFunc(t*testing.T) {htest.NewClient(t).ToFunc(NameHandler).Get("").Test().StatusOK().JSON().String("name","hexi")}
You can also test handler (*http.ServeMux, *echo.Echo .etc.)
// example/basic_mock_client.gopackage myappimport ("io""net/http")var (Mux*http.ServeMux)funcinit() {Mux=http.NewServeMux()Mux.HandleFunc("/name",NameHandler)}funcNameHandler(w http.ResponseWriter,req*http.Request) {io.WriteString(w,`{"name": "hexi"}`)}
// example/basic_mock_client_test.gopackage myappimport ("testing""github.com/Hexilee/htest")funcTestNameHandler(t*testing.T) {htest.NewClient(t).To(Mux).Get("/name").Test().StatusOK().JSON().String("name","hexi")}
// example/basic_mock_client.gopackage myappimport ("io""github.com/labstack/echo")var (server*echo.Echo)funcinit() {server=echo.New()server.GET("/name",NameHandlerEcho)}funcNameHandlerEcho(c echo.Context)error {returnc.String(http.StatusOK,`{"name": "hexi"}`)}
// example/basic_mock_client_test.gopackage myappimport ("testing""github.com/Hexilee/htest")funcTestNameHandlerEcho(t*testing.T) {htest.NewClient(t).To(server).Get("/name").Test().StatusOK().JSON().String("name","hexi")}
Send a http request and test the response
// request_test.gofuncTestRequest_Send(t*testing.T) {NewClient(t).Get("https://api.github.com/users/Hexilee").Send().StatusOK().JSON().String("login","Hexilee")}
Set mock server to be tested (Do not need it when you test real server)
Set a HandlerFunc as mock server
// example/basic_mock_client_test.gopackage myappimport ("testing""github.com/Hexilee/htest")funcTestNameHandlerFunc(t*testing.T) {htest.NewClient(t).ToFunc(NameHandler).Get("").Test().StatusOK().JSON().String("name","hexi")}
Set a Handler as mock server
// example/basic_mock_client_test.gopackage myappimport ("testing""github.com/Hexilee/htest")funcTestNameHandler(t*testing.T) {htest.NewClient(t).To(Mux).Get("/name").Test().StatusOK().JSON().String("name","hexi")}
Construct htest.Request using different http methods
For example
- Get
// client.gofunc (cClient)Get(pathstring)*Request
More
- Head
- Trace
- Options
- Connect
- Delete
- Post
- Put
- Patch
Set headers and return *Request for chaining-call
- SetHeader
// server_test.goMux.Get("/request/header",HeaderHandler)// request_test.gofuncHeaderHandler(w http.ResponseWriter,req*http.Request) {ifreq.Header.Get(HeaderContentType)==MIMEApplicationJSON {io.WriteString(w,`{"result": "JSON"}`)return}http.Error(w,http.StatusText(http.StatusBadRequest),http.StatusBadRequest)}funcTestRequest_SetHeader(t*testing.T) {client:=NewClient(t).To(Mux)// bad content typeclient.Get("/request/header").SetHeader(HeaderContentType,MIMEApplicationForm).Test().StatusBadRequest()// rightclient.Get("/request/header").SetHeader(HeaderContentType,MIMEApplicationJSON).Test().StatusOK().JSON().String("result","JSON")}
HeaderContentType, MIMEApplicationForm are constants in const.goFor more information, you can refer toAppendix
- SetHeaders
// request_test.gofuncTestRequest_SetHeaders(t*testing.T) {client:=NewClient(t).To(Mux)// bad content typeclient.Get("/request/header").SetHeaders(map[string]string{HeaderContentType:MIMEApplicationForm,},).Test().StatusBadRequest()// rightclient.Get("/request/header").SetHeaders(map[string]string{HeaderContentType:MIMEApplicationJSON,},).Test().StatusOK().JSON().String("result","JSON")}
Add cookie and return *Request for chaining-call
// server_test.goMux.Get("/request/cookie",CookieHandler)// request_test.govar (testCookie= http.Cookie{Name:"test_cookie",Value:"cookie_value"})funcCookieHandler(w http.ResponseWriter,req*http.Request) {cookie,err:=req.Cookie(testCookie.Name)iferr!=nil {http.Error(w,http.StatusText(http.StatusForbidden),http.StatusForbidden)return}io.WriteString(w,fmt.Sprintf(`{"cookie": "%s"}`,cookie))}funcTestRequest_AddCookie(t*testing.T) {client:=NewClient(t).To(Mux)client.Get("/request/cookie").Test().StatusForbidden()client.Get("/request/cookie").AddCookie(&testCookie).Test().StatusOK().JSON().String("cookie",testCookie.String())}
Calling *Request.Test will test the mock server and return a *Response.
You must have called Client.To or Client.ToFunc, otherwise causing a panic (htest.MockNilError)
// request_test.gofuncTestRequest_Test(t*testing.T) {deferfunc() {assert.Equal(t,MockNilError,recover())}()NewClient(t).Get("/request/header").SetHeader(HeaderContentType,MIMEApplicationForm).Test().StatusBadRequest()}
Calling *Request.Send will send a real http request and return a *Response
// request_test.gofuncTestRequest_Send(t*testing.T) {NewClient(t).Get("https://api.github.com/users/Hexilee").Send().StatusOK().JSON().String("login","Hexilee")}
As *http.Request is embedded in htest.Request, you can regard *htest.Request as *http.Request. Just like:
userAgent:=NewClient(t).Get("https://api.github.com/users/Hexilee").UserAgent()
Assert Response.StatusCode
*Response.Code(statusCode int)
// response_test.govar (ResponseCodeServer=chi.NewRouter())funcinit() {ResponseCodeServer.Get("/response/statusCode/{code}",StatusHandler)}funcStatusHandler(w http.ResponseWriter,req*http.Request) {codeStr:=chi.URLParam(req,"code")code,err:=strconv.Atoi(codeStr)iferr!=nil {w.WriteHeader(http.StatusNotFound)return}w.WriteHeader(code)}funcTestResponse_Code(t*testing.T) {NewClient(t).To(ResponseCodeServer).Get(fmt.Sprintf("/response/statusCode/%d",http.StatusBadRequest)).Test().Code(http.StatusBadRequest)}
For more ergonomic development, *htest.Response has many methods to assert all the StatusCode in net/http
// response_test.gofuncTestResponse_StatusContinue(t*testing.T) {NewClient(t).To(ResponseCodeServer).Get(fmt.Sprintf("/response/statusCode/%d",http.StatusContinue)).Test().StatusContinue()}
Assert Response.Headlers
*Response.Headers(key, expect string)
// response_test.govar (ResponseHeadersServer=chi.NewRouter())funcinit() {ResponseHeadersServer.Get("/response/headers",HeadersHandler)}funcHeadersHandler(w http.ResponseWriter,req*http.Request) {query:=req.URL.Query()header:=query.Get("header")value:=query.Get("value")w.Header().Set(header,value)}funcTestResponse_Headers(t*testing.T) {url:=fmt.Sprintf("/response/headers?header=%s&value=%s",HeaderContentType,MIMEApplicationJSON)NewClient(t).To(ResponseHeadersServer).Get(url).Test().Headers(HeaderContentType,MIMEApplicationJSON)}
For more ergonomic development, *htest.Response has many methods to assert all the Headers in const.go
// response_test.gofuncTestResponse_HeaderAccept(t*testing.T) {url:=fmt.Sprintf("/response/headers?header=%s&value=%s",HeaderAccept,"htest")NewClient(t).To(ResponseHeadersServer).Get(url).Test().HeaderAccept("htest")}
You can assert data in body straightly.
// server_test.goMux.Get("/body/user",UserDataHandler)funcUserDataHandler(w http.ResponseWriter,req*http.Request) {io.WriteString(w,UserData)}// response_test.goconst (UserData=`{"id": 1,"name": "hexi"}`)funcTestResponse_Expect(t*testing.T) {NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().Expect(UserData)}
You can get data in body straightly
- String
// response_test.gofuncTestResponse_String(t*testing.T) {assert.Equal(t,UserData,NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().String())}
- Bytes
// response_test.gofuncTestResponse_Bytes(t*testing.T) {assert.Equal(t, []byte(UserData),NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().Bytes())}
If type of data in body is JSON, you can unmarshal it straightly
// response_test.gotype (Userstruct {IduintNamestring})funcTestResponse_Bind(t*testing.T) {user:=new(User)NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().Bind(user)assert.Equal(t,user.Id,uint(1))assert.Equal(t,user.Name,"hexi")}
You can return data in 4 types
As *http.Response is embedded in htest.Response, you can regard *htest.Response as *http.Response. Just like:
assert.Equal(t,"HTTP/1.1",NewClient(t).To(Mux).Get("/body/user").Test().Proto)
htest provide 4 types of data to be returned
data as JSON
- Exist(key string)
- NotExist(key string)
- String(key, expect string)
- Int(key string, expect int64)
- True(key string)
- False(key string)
- Uint(key string, expect uint64)
- Time(key string, expect time.Time)
- Float(key string, expect float64)
// body_test.gofuncTestJSON_Exist(t*testing.T) {NewClient(t).To(Mux).Get("/name").Test().StatusOK().JSON().Exist("name").NotExist("stuid")}
funcTestJSON_String(t*testing.T) {user:=new(User)NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().JSON().String("name", "hexi)}
funcTestJSON_NotEmpty(t*testing.T) {user:=new(User)NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().JSON().NotEmpty()}
// body_test.gotype (Userstruct {IduintNamestring})funcTestJSON_Bind(t*testing.T) {user:=new(User)NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().JSON().Bind(user)assert.Equal(t,user.Id,uint(1))assert.Equal(t,user.Name,"hexi")}
Same as JSON.
For more examples, you can find them in body_test.go
// body_test.gofuncTestMD5_Expect(t*testing.T) {NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().MD5().Expect(UserDataMD5)}
hash:=NewClient(t).To(Mux).Get("/body/user").Test().StatusOK().MD5().Body()
Same as MD5.
For more examples, you can find them in body_test.go
There are many constants of header or header value in const.go
// const.gopackage htest// HTTP methodsconst (CONNECT="CONNECT"DELETE="DELETE"GET="GET"HEAD="HEAD"OPTIONS="OPTIONS"PATCH="PATCH"POST="POST"PUT="PUT"TRACE="TRACE")// MIME typesconst (MIMEApplicationJSON="application/json"MIMEApplicationJSONCharsetUTF8=MIMEApplicationJSON+"; "+charsetUTF8MIMEApplicationJavaScript="application/javascript"MIMEApplicationJavaScriptCharsetUTF8=MIMEApplicationJavaScript+"; "+charsetUTF8MIMEApplicationXML="application/xml"MIMEApplicationXMLCharsetUTF8=MIMEApplicationXML+"; "+charsetUTF8MIMETextXML="text/xml"MIMETextXMLCharsetUTF8=MIMETextXML+"; "+charsetUTF8MIMEApplicationForm="application/x-www-form-urlencoded"MIMEApplicationProtobuf="application/protobuf"MIMEApplicationMsgpack="application/msgpack"MIMETextHTML="text/html"MIMETextHTMLCharsetUTF8=MIMETextHTML+"; "+charsetUTF8MIMETextPlain="text/plain"MIMETextPlainCharsetUTF8=MIMETextPlain+"; "+charsetUTF8MIMEMultipartForm="multipart/form-data"MIMEOctetStream="application/octet-stream")const (charsetUTF8="charset=UTF-8")// Headersconst (HeaderAccept="Accept"HeaderAcceptEncoding="Accept-Encoding"HeaderAllow="Allow"HeaderAuthorization="Authorization"HeaderContentDisposition="Content-Disposition"HeaderContentEncoding="Content-Encoding"HeaderContentLength="Content-Length"HeaderContentType="Content-Type"HeaderCookie="Cookie"HeaderSetCookie="Set-Cookie"HeaderIfModifiedSince="If-Modified-Since"HeaderLastModified="Last-Modified"HeaderLocation="Location"HeaderUpgrade="Upgrade"HeaderVary="Vary"HeaderWWWAuthenticate="WWW-Authenticate"HeaderXForwardedFor="X-Forwarded-For"HeaderXForwardedProto="X-Forwarded-Proto"HeaderXForwardedProtocol="X-Forwarded-Protocol"HeaderXForwardedSsl="X-Forwarded-Ssl"HeaderXUrlScheme="X-Url-Scheme"HeaderXHTTPMethodOverride="X-HTTP-Method-Override"HeaderXRealIP="X-Real-IP"HeaderXRequestID="X-Request-ID"HeaderServer="Server"HeaderOrigin="Origin"// Access controlHeaderAccessControlRequestMethod="Access-Control-Request-Method"HeaderAccessControlRequestHeaders="Access-Control-Request-Headers"HeaderAccessControlAllowOrigin="Access-Control-Allow-Origin"HeaderAccessControlAllowMethods="Access-Control-Allow-Methods"HeaderAccessControlAllowHeaders="Access-Control-Allow-Headers"HeaderAccessControlAllowCredentials="Access-Control-Allow-Credentials"HeaderAccessControlExposeHeaders="Access-Control-Expose-Headers"HeaderAccessControlMaxAge="Access-Control-Max-Age"// SecurityHeaderStrictTransportSecurity="Strict-Transport-Security"HeaderXContentTypeOptions="X-Content-Type-Options"HeaderXXSSProtection="X-XSS-Protection"HeaderXFrameOptions="X-Frame-Options"HeaderContentSecurityPolicy="Content-Security-Policy"HeaderXCSRFToken="X-CSRF-Token")
About
htest is a http-test package