tester

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Mar 23, 2025 License: MIT Imports: 20 Imported by: 0

README

tester

Simple testing package for restful APIs.

Usage

Tester provides a simple way to test restful APIs. It is based on the testing package and provides a simple way to test APIs. It provides two main functions:

  • WithHttpServer - starts a http server and runs given closure with the server
  • WithAPI - runs given closure with the API client

Example

Let's see an example of how to use the tester package.

package main

import (
	"context"
	"encoding/json"
	"github.com/gorilla/mux"
	"github.com/phonkee/jayson/tester"
	"github.com/phonkee/jayson/tester/action"
	"github.com/phonkee/jayson/tester/resolver"
	"github.com/stretchr/testify/assert"
	"net/http"
	"regexp"
	"testing"
)

type User struct {
	ID   int    `json:"id"`
	Name string `json:"name"`
}

func ListUsers(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusOK)
	w.Header().Set("Content-Type", "application/json")
	_, _ = w.Write([]byte(`{"users": [{"id":1,"name":"John Doe"}]}`))
}

func TestTester(t *testing.T) {
	router := mux.NewRouter()
	router.HandleFunc("/users", ListUsers).Methods(http.MethodGet).Name("api:v1:users:list")

	tester.WithHttpServer(t, context.Background(), router, func(t *testing.T, ctx context.Context, address string) {
		// test api
		tester.WithAPI(t, &tester.Deps{
			Resolver: resolver.NewGorillaResolver(t, router),
			Address:  address,
		}, func(api tester.APIClient) {
			user := User{}
			userObj := User{}
			api.Get(t, api.ReverseURL(t, "api:v1:users:list")).
				Do(t, ctx).
				Status(t, action.AssertEquals(http.StatusOK)).
				Json(t, "users.0.name", action.AssertNot(action.AssertEquals("Johnson Doe"))).
				Json(t, "users.0.name", action.AssertEquals("John Doe")).
				Json(t, "users.0", action.AssertEquals(json.RawMessage(`{"id":1,"name":"John Doe"}`))).
				Json(t, "users.0.name", action.AssertIn("John Doe", "Peter Vrba")).
				Json(t, "users.0.name", action.AssertNot(action.AssertIn("Johnson Doe", "Peter Vrba"))).
				Json(t, "users", action.AssertExists()).
				Json(t, "user", action.AssertNot(action.AssertExists())).
				Json(t, "users", action.AssertLen(1)).
				Json(t, "users.0", action.AssertKeys("id", "name")).
				Json(t, "users.0.id", action.AssertGte(1)).
				Json(t, "users.0.id", action.AssertGt(0)).
				Json(t, "users.0.id", action.AssertLt(2)).
				Json(t, "users.0.id", action.AssertLte(1)).
				Json(t, "users.0", action.Unmarshal(&user)).
				Json(t, "users.0.id", action.AssertAll(
					action.AssertGte(0),
					action.AssertLte(1),
					action.AssertExists(),
				)).
				Json(t, "users.0.id", action.AssertAny(
					action.AssertGte(0),
					action.AssertLte(0),
					action.AssertNot(action.AssertExists()),
				)).
				Json(t, "users.0.id", action.AssertRegexMatch(
					regexp.MustCompile(`\d+`),
				)).
				Json(t, "users.0", action.UnmarshalObjectKeys(action.KV{
					"id":   &userObj.ID,
					"name": &userObj.Name,
				}))

			// test Unmarshal
			assert.Equal(t, user.ID, 1)
			assert.Equal(t, user.Name, "John Doe")

			// test UnmarshalObjectKeys
			assert.Equal(t, userObj.ID, 1)
			assert.Equal(t, userObj.Name, "John Doe")
		})
	})
}

TODO

Author

Peter Vrba phonkee@phonkee.eu

Documentation

Index

Constants

View Source
const (
	// ContentTypeHeader is the content type header
	ContentTypeHeader = "Content-Type"
	// ContentTypeJSON is the content type for json
	ContentTypeJSON = "application/json"
)
View Source
const (
	// RootPath is the root path for Response Json call
	RootPath string = ""
)

Variables

This section is empty.

Functions

func NewReadCloser added in v0.6.0

func NewReadCloser(r io.Reader) io.ReadCloser

NewReadCloser creates a new readCloser wrapping the given io.Reader

func WithAPI

func WithAPI(t require.TestingT, deps *Deps, fn func(APIClient))

WithAPI runs the given function with a new APIClient instance

func WithHttpServer added in v0.5.0

func WithHttpServer(t *testing.T, ctx context.Context, handler http.Handler, fn func(t *testing.T, ctx context.Context, address string))

WithHttpServer runs a new HTTP server with the provided handler and calls the provided function with the server address.

Types

type APIClient

type APIClient interface {
	// Delete does a DELETE response to the APIClient
	Delete(t require.TestingT, path string) APIRequest

	// Get does a GET response to the APIClient
	Get(t require.TestingT, path string) APIRequest

	// Post does a POST response to the APIClient
	Post(t require.TestingT, path string) APIRequest

	// Put does a PUT response to the APIClient
	Put(t require.TestingT, path string) APIRequest

	// Request does a response to the APIClient
	Request(t require.TestingT, method string, path string) APIRequest

	// ReverseURL creates a path by given url name and url arguments
	ReverseURL(t require.TestingT, name string, extra ...resolver.Extra) string

	// ReverseArgs creates a resolver.Extra from given key value pairs
	ReverseArgs(t require.TestingT, kv ...string) resolver.Extra

	// ReverseQuery creates a resolver.Extra from given key value pairs
	ReverseQuery(t require.TestingT, kv ...string) resolver.Extra
}

APIClient is the interface for testing the rest APIClient

type APIRequest

type APIRequest interface {
	// Body sets the body of the request
	Body(t require.TestingT, body any) APIRequest

	// Do perform the request and returns the response
	Do(t require.TestingT, ctx context.Context) APIResponse

	// Header sets the header of the request
	Header(t require.TestingT, key, value string) APIRequest

	// Print the response to stdout
	Print(writer ...io.Writer) APIRequest

	// Query sets the query of the request
	Query(t require.TestingT, key, value string) APIRequest
}

APIRequest is the interface for testing the rest APIClient response

type APIResponse

type APIResponse interface {

	// Print the response to stdout
	Print(writer ...io.Writer) APIResponse

	// Header asserts that response header action is equal to given action
	Header(t require.TestingT, key string, action action.Action) APIResponse

	// Json calls the action on the json response path
	Json(t require.TestingT, path string, action action.Action) APIResponse

	// Status asserts that response status is equal to given action
	Status(t require.TestingT, action action.Action) APIResponse
}

APIResponse is the interface for testing the rest APIClient response

type Deps

type Deps struct {
	// Handler is the http.Handler
	Handler http.Handler
	// Addr is the address of the server (host:port)
	Address string
	// Client sets custom http client
	Client *http.Client
	// Resolver is the URL resolver
	Resolver resolver.Resolver
}

Deps is the dependencies for the APIClient Resolve provides ReverseURL method, but is only optional One of Handler or Address is required

func (*Deps) ReverseArgs added in v0.5.0

func (d *Deps) ReverseArgs(t require.TestingT, kv ...string) resolver.Extra

ReverseArgs adds arguments key action pairs to resolver.Extra for ReverseURL

func (*Deps) ReverseQuery added in v0.5.0

func (d *Deps) ReverseQuery(t require.TestingT, kv ...string) resolver.Extra

ReverseQuery adds query key action pairs to resolver.Extra for ReverseURL

func (*Deps) ReverseURL added in v0.5.0

func (d *Deps) ReverseURL(t require.TestingT, name string, extra ...resolver.Extra) string

ReverseURL resolves URL by name

func (*Deps) Validate

func (d *Deps) Validate(t require.TestingT)

Validate deps

type RoundTripper added in v0.5.0

type RoundTripper interface {
	http.RoundTripper
}

type TestingT added in v0.5.0

type TestingT interface {
	require.TestingT
}

TestingT is a mock implementation of the require.TestingT interface.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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