httpspec

package
v0.16.2 Latest Latest
Warning

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

Go to latest
Published: Nov 18, 2020 License: Apache-2.0 Imports: 11 Imported by: 0

README

Table of Contents generated with DocToc

httpspec

httpspec allow you to create HTTP API specifications with ease.

Documentation

The documentation maintained in GoDoc, including the examples.

Usage

package mypkg_test

import (
	"encoding/json"
	"net/http"
	"testing"

	"my/pkg/path/mypkg"

	"github.com/stretchr/testify/require"

	"github.com/adamluzsi/testcase"
	. "github.com/adamluzsi/testcase/httpspec"
)

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

	GivenThisIsAJSONAPI(s)

	// Arrange
	LetHandler(s, func(t *testcase.T) http.Handler { return mypkg.MyHandler{} })
	LetMethodValue(s, http.MethodPost)
	LetPathValue(s, `/`)
	LetBody(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) {
		rr := ServeHTTP(t) // Act
		require.Equal(t, http.StatusOK, rr.Code)
		var resp mypkg.CreateResponse
		require.Nil(t, json.Unmarshal(rr.Body.Bytes(), &resp))
		// more assertion
	})
}
package mypkg_test

import (
	"encoding/json"
	"net/http"
	"testing"

	"my/pkg/path/mypkg"

	"github.com/stretchr/testify/require"

	"github.com/adamluzsi/testcase"
	. "github.com/adamluzsi/testcase/httpspec"
)

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

	GivenThisIsAJSONAPI(s)

	LetHandler(s, func(t *testcase.T) http.Handler { return mypkg.MyHandler{} })

	s.Describe(`POST / - create X`, func(s *testcase.Spec) {
		LetMethodValue(s, http.MethodPost)
		LetPathValue(s, `/`)

		LetBody(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) mypkg.CreateResponse {
			rr := ServeHTTP(t)
			require.Equal(t, http.StatusOK, rr.Code)
			var resp mypkg.CreateResponse
			require.Nil(t, 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
		})
	})
}

Documentation

Index

Examples

Constants

View Source
const (
	ContextVarName = letVarPrefix + `context`
)

Variables

This section is empty.

Functions

func ContentTypeIsJSON added in v0.13.0

func ContentTypeIsJSON(s *testcase.Spec)

func Debug added in v0.5.1

func Debug(s *testcase.Spec)

func HandlerSpec added in v0.13.0

func HandlerSpec(s *testcase.Spec, subject func(t *testcase.T) http.Handler)

HandlerSpec 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.

func Header(t *testcase.T) http.Header

Header allows you to set the current test scope's http path for ServeHTTP.

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler { return MyHandler{} })

s.Before(func(t *testcase.T) {
	// this is ideal to represent query string inputs
	httpspec.Header(t).Set(`Foo`, `bar`)
})

s.Test(`the *http.Request URL Query will have 'Foo: bar'`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

func LetBody

func LetBody(s *testcase.Spec, f func(t *testcase.T) interface{})

LetBody allow you to define a http request body value for the ServeHTTP. The value of this can be a struct, map or url.Values. The Serialization for the request body is based on the Header "Content-Type" value. Currently only json and form url encoding is supported.

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler { return MyHandler{} })

httpspec.LetBody(s, func(t *testcase.T) interface{} {
	return map[string]string{"hello": "world"}
})

s.Before(func(t *testcase.T) {
	// this set the content-type for json, so json marshal will be used.
	httpspec.Header(t).Set(`Content-Type`, `application/json`)
})

s.Test(`the *http.Request body io.Reader will have the encoded body`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

func LetContext

func LetContext(s *testcase.Spec, f func(t *testcase.T) context.Context)

LetContext allow you to Set the ServeHTTP request context

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler { return MyHandler{} })

httpspec.LetContext(s, func(t *testcase.T) context.Context {
	return context.Background()
})

s.Test(`the *http.Request#Context() will have foo-bar`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

Example (WithValue)
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler { return MyHandler{} })

s.Before(func(t *testcase.T) {
	// this is ideal for representing middleware prerequisite
	// in the form of a value in the context that is guaranteed by a middleware.
	// Use this only if you cannot make it part of the specification level context value deceleration with LetContext.
	ctx := t.I(httpspec.ContextVarName).(context.Context)
	ctx = context.WithValue(ctx, `foo`, `bar`)
	t.Let(httpspec.ContextVarName, ctx)
})

s.Test(`the *http.Request#Context() will have foo-bar`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

func LetMethod

func LetMethod(s *testcase.Spec, f func(t *testcase.T) string)

LetMethod allow you to set the current test scope's http method for ServeHTTP

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler {
	return MyHandler{}
})

httpspec.LetMethod(s, func(t *testcase.T) string {
	// set the HTTP Method to get for the *http.Request
	return http.MethodGet
})

s.Test(`GET /`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

func LetMethodValue

func LetMethodValue(s *testcase.Spec, m string)

LetMethodValue allow you to set the current test scope's http method for ServeHTTP

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler {
	return MyHandler{}
})

// set the HTTP Method to get for the *http.Request
httpspec.LetMethodValue(s, http.MethodGet)

s.Test(`GET /`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

func LetPath

func LetPath(s *testcase.Spec, f func(t *testcase.T) string)

LetPath allows you to set the current test scope's http path for ServeHTTP.

func LetPathValue

func LetPathValue(s *testcase.Spec, p string)

LetPathValue allows you to set the current test scope's http path for ServeHTTP.

func Query

func Query(t *testcase.T) url.Values

Query allows you to retrieve the current test scope's http path query that will be used for ServeHTTP. In a Before Block you can access the query and then specify the values in it.

Example
s := testcase.NewSpec(testingT)

httpspec.HandlerSpec(s, func(t *testcase.T) http.Handler { return MyHandler{} })

s.Before(func(t *testcase.T) {
	// this is ideal to represent query string inputs
	httpspec.Query(t).Set(`foo`, `bar`)
})

s.Test(`the *http.Request URL Query will have foo=bar`, func(t *testcase.T) {
	httpspec.ServeHTTP(t)
})
Output:

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 method <string>
  • path -> http path <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