Documentation
¶
Overview ¶
Example (Usage) ¶
var tb testing.TB s := testcase.NewSpec(tb) // subject httpspec.Handler.Let(s, func(t *testcase.T) http.Handler { return MyHandler{} }) // Arrange httpspec.ContentTypeIsJSON(s) httpspec.Method.LetValue(s, http.MethodPost) httpspec.Path.LetValue(s, `/`) httpspec.Body.Let(s, func(t *testcase.T) interface{} { // this will end up as {"foo":"bar"} in the request body return map[string]string{"foo": "bar"} }) s.Then(`it will...`, func(t *testcase.T) { // ServeHTTP rr := httpspec.ServeHTTP(t) // Assert t.Must.Equal(http.StatusOK, rr.Code) var resp CreateResponse t.Must.Nil(json.Unmarshal(rr.Body.Bytes(), &resp)) // ... })
Output:
Example (UsageWithDotImport) ¶
s := testcase.NewSpec(testingT) Handler.Let(s, func(t *testcase.T) http.Handler { return MyHandler{} }) s.Before(func(t *testcase.T) { t.Log(`given authentication header is set`) Header.Get(t).Set(`X-Auth-Token`, `token`) }) s.Describe(`GET / - list of X`, func(s *testcase.Spec) { Method.LetValue(s, http.MethodGet) Path.LetValue(s, `/`) var onSuccess = func(t *testcase.T) ListResponse { rr := ServeHTTP(t) t.Must.Equal(http.StatusOK, rr.Code) // unmarshal the response from rr.body return ListResponse{} } s.And(`something is set in the query`, func(s *testcase.Spec) { s.Before(func(t *testcase.T) { Query.Get(t).Set(`something`, `value`) }) s.Then(`it will react to it as`, func(t *testcase.T) { listResponse := onSuccess(t) // assert _ = listResponse }) }) s.Then(`it will return the list of resource`, func(t *testcase.T) { listResponse := onSuccess(t) // assert _ = listResponse }) }) s.Describe(`GET /{resourceID} - show X`, func(s *testcase.Spec) { Method.LetValue(s, http.MethodGet) Path.Let(s, func(t *testcase.T) string { return fmt.Sprintf(`/%s`, t.Random.String()) }) var onSuccess = func(t *testcase.T) ShowResponse { rr := ServeHTTP(t) t.Must.Equal(http.StatusOK, rr.Code) // unmarshal the response from rr.body return ShowResponse{} } s.Then(`it will return the resource 'show'' representation`, func(t *testcase.T) { showResponse := onSuccess(t) // assert _ = showResponse }) })
Output:
Index ¶
- Variables
- func ClientDo(t *testcase.T, srv *httptest.Server, r *http.Request) (*http.Response, error)
- func ContentTypeIsJSON(s *testcase.Spec)
- func Debug(s *testcase.Spec)
- func ItBehavesLikeHandlerMiddleware(s *testcase.Spec, subject MakeHandlerMiddlewareFunc)
- func ItBehavesLikeRoundTripperMiddleware(s *testcase.Spec, subject MakeRoundTripperFunc)
- func LetRequest(s *testcase.Spec, rv RequestVar) testcase.Var[*http.Request]
- func LetResponseRecorder(s *testcase.Spec) testcase.Var[*httptest.ResponseRecorder]
- func LetRoundTripperDouble(s *testcase.Spec) testcase.Var[*RoundTripperDouble]
- func LetServer(s *testcase.Spec, handler testcase.VarInit[http.Handler]) testcase.Var[*httptest.Server]
- func ServeHTTP(t *testcase.T) *httptest.ResponseRecorder
- type HandlerMiddlewareContract
- type MakeHandlerMiddlewareFunc
- type MakeRoundTripperFunc
- type RequestVar
- type RoundTripperDouble
- type RoundTripperFunc
- type RoundTripperMiddlewareContract
Examples ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( // Handler prepares the current testcase spec scope to be ready for http handler testing. // You define your spec subject with this and all the request will be pointed towards this. Handler = testcase.Var[http.Handler]{ID: `httpspec:Handler`} // Context allow to retrieve the current test scope's request context. Context = testcase.Var[context.Context]{ID: `httpspec:Context`, Init: func(t *testcase.T) context.Context { return context.Background() }} Method = testcase.Var[string]{ID: `httpspec:Method`, Init: func(t *testcase.T) string { return http.MethodGet }} Path = testcase.Var[string]{ID: `httpspec:Path`, Init: func(t *testcase.T) string { return `/` }} // Query allows you to retrieve the current test scope's http PathGet query that will be used for ServeHTTP. // In a Before Block you can access the query and then specify the values in it. Query = testcase.Var[url.Values]{ID: `httpspec:Query`, Init: func(t *testcase.T) url.Values { return url.Values{} }} // Header allows you to set the current test scope's http PathGet for ServeHTTP. Header = testcase.Var[http.Header]{ID: `httpspec:Header.Get`, Init: func(t *testcase.T) http.Header { return http.Header{} }} )
View Source
var ( InboundRequest = testcase.Var[*http.Request]{ ID: "httpspec:InboundRequest", Init: func(t *testcase.T) *http.Request { target, _ := url.Parse(Path.Get(t)) target.RawQuery = Query.Get(t).Encode() if isDebugEnabled(t) { t.Log(`http.InboundRequest.Method:`, Method.Get(t)) t.Log(`http.InboundRequest.Path`, target.String()) } r := httptest.NewRequest(Method.Get(t), target.String(), asIOReader(t, Header.Get(t), Body.Get(t))) r = r.WithContext(Context.Get(t)) r.Header = Header.Get(t) return r }, } OutboundRequest = testcase.Var[*http.Request]{ ID: "httpspec:OutboundRequest", Init: func(t *testcase.T) *http.Request { u := url.URL{ Scheme: t.Random.ElementFromSlice([]string{"http", "https"}).(string), Host: fmt.Sprintf("www.%s.com", t.Random.StringNC(7, random.CharsetAlpha())), Path: Path.Get(t), RawPath: Path.Get(t), RawQuery: Query.Get(t).Encode(), } if isDebugEnabled(t) { t.Log(`http.OutboundRequest.Method:`, Method.Get(t)) t.Log(`http.OutboundRequest.Path`, u.Path) } r, err := http.NewRequest(Method.Get(t), u.String(), asIOReader(t, Header.Get(t), Body.Get(t))) t.Must.Nil(err) r = r.WithContext(Context.Get(t)) r.Header = Header.Get(t) return r }, } ResponseRecorder = testcase.Var[*httptest.ResponseRecorder]{ ID: "httpspec:ResponseRecorder", Init: func(t *testcase.T) *httptest.ResponseRecorder { return httptest.NewRecorder() }, } Response = testcase.Var[*http.Response]{ ID: "httpspec:Response", Init: func(t *testcase.T) *http.Response { code := t.Random.ElementFromSlice([]int{ http.StatusOK, http.StatusTeapot, http.StatusInternalServerError, }).(int) body := t.Random.String() return &http.Response{ Status: http.StatusText(code), StatusCode: code, Proto: "HTTP/1.0", ProtoMajor: 1, ProtoMinor: 0, Header: http.Header{ "X-" + t.Random.StringNWithCharset(5, "ABCD"): {t.Random.StringNWithCharset(5, "ABCD")}, }, Body: io.NopCloser(strings.NewReader(body)), ContentLength: int64(len(body)), } }, } )
View Source
var Body = testcase.Var[any]{ID: `httpspec:Body`, Init: func(t *testcase.T) any { return &bytes.Buffer{} }}
View Source
var Request = InboundRequest
Request
DEPRECATED: use InboundRequest instead
Functions ¶
func ContentTypeIsJSON ¶ added in v0.13.0
Example ¶
s := testcase.NewSpec(testingT) Handler.Let(s, func(t *testcase.T) http.Handler { return MyHandler{} }) ContentTypeIsJSON(s) s.Describe(`POST / - create X`, func(s *testcase.Spec) { Method.LetValue(s, http.MethodPost) Path.LetValue(s, `/`) Body.Let(s, func(t *testcase.T) interface{} { // this will end up as {"foo":"bar"} in the request body return map[string]string{"foo": "bar"} }) var onSuccess = func(t *testcase.T) CreateResponse { rr := ServeHTTP(t) assert.Must(t).Equal(http.StatusOK, rr.Code) var resp CreateResponse assert.Must(t).Nil(json.Unmarshal(rr.Body.Bytes(), &resp)) return resp } s.Then(`it will create a new resource`, func(t *testcase.T) { createResponse := onSuccess(t) // assert _ = createResponse }) })
Output:
func ItBehavesLikeHandlerMiddleware ¶ added in v0.84.0
func ItBehavesLikeHandlerMiddleware(s *testcase.Spec, subject MakeHandlerMiddlewareFunc)
func ItBehavesLikeRoundTripperMiddleware ¶ added in v0.76.2
func ItBehavesLikeRoundTripperMiddleware(s *testcase.Spec, subject MakeRoundTripperFunc)
func LetRequest ¶ added in v0.98.0
func LetResponseRecorder ¶ added in v0.95.0
func LetRoundTripperDouble ¶ added in v0.111.0
func LetRoundTripperDouble(s *testcase.Spec) testcase.Var[*RoundTripperDouble]
func ServeHTTP ¶
func ServeHTTP(t *testcase.T) *httptest.ResponseRecorder
ServeHTTP will make a request to the spec context it requires the following spec variables
- Method -> http MethodGet <string>
- Path -> http PathGet <string>
- Query -> http query string <url.Values>
- Body -> http payload <io.Reader|io.ReadCloser>
Types ¶
type HandlerMiddlewareContract ¶ added in v0.84.0
type HandlerMiddlewareContract struct { Subject MakeHandlerMiddlewareFunc MakeCTX testcase.VarInit[context.Context] }
func (HandlerMiddlewareContract) Spec ¶ added in v0.84.0
func (c HandlerMiddlewareContract) Spec(s *testcase.Spec)
type MakeHandlerMiddlewareFunc ¶ added in v0.84.0
type MakeRoundTripperFunc ¶ added in v0.84.0
type MakeRoundTripperFunc func(t *testcase.T, next http.RoundTripper) http.RoundTripper
type RequestVar ¶ added in v0.98.0
type RoundTripperDouble ¶ added in v0.110.0
type RoundTripperDouble struct { // RoundTripperFunc is an optional argument in case you want to stub the response RoundTripperFunc RoundTripperFunc // ReceivedRequests hold all the received http request. ReceivedRequests []*http.Request }
func (*RoundTripperDouble) LastReceivedRequest ¶ added in v0.110.0
func (d *RoundTripperDouble) LastReceivedRequest(tb testing.TB) *http.Request
type RoundTripperFunc ¶ added in v0.110.0
type RoundTripperMiddlewareContract ¶ added in v0.76.2
type RoundTripperMiddlewareContract struct { Subject MakeRoundTripperFunc MakeCTX testcase.VarInit[context.Context] }
func (RoundTripperMiddlewareContract) Spec ¶ added in v0.76.2
func (c RoundTripperMiddlewareContract) Spec(s *testcase.Spec)
Click to show internal directories.
Click to hide internal directories.