httpspec

package
v0.67.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 15, 2022 License: Apache-2.0 Imports: 11 Imported by: 0

README

httpspec

httpspec allow you to create HTTP API specifications with ease.

Documentation

The documentation maintained in GoDoc, including the examples.

Usage

package mypkg

func TestMyHandlerCreate(t *testing.T) {
	s := testcase.NewSpec(t)

	// subject
	httpspec.SubjectLet(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) {
		// Act
		rr := httpspec.SubjectGet(t)

		// Assert
		assert.Must(t).Equal( http.StatusOK, rr.Code)
		var resp CreateResponse
		assert.Must(t).Nil( json.Unmarshal(rr.Body.Bytes(), &resp))
		// ...
	})
}

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

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 `/`
	}}
	Body = testcase.Var[any]{ID: `httpspec:Body`, Init: func(t *testcase.T) any {
		return &bytes.Buffer{}
	}}
	// 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:QueryGet`, 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{}
	}}
)

Functions

func ContentTypeIsJSON added in v0.13.0

func ContentTypeIsJSON(s *testcase.Spec)
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 Debug added in v0.5.1

func Debug(s *testcase.Spec)

func ServeHTTP

func ServeHTTP(t *testcase.T) *httptest.ResponseRecorder

ServeHTTP will make a request to the spec context it requires the following spec variables

  • MethodGet -> http MethodGet <string>
  • PathGet -> http PathGet <string>
  • query -> http query string <url.Values>
  • body -> http payload <io.Reader|io.ReadCloser>

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL