gock

package module
v0.1.6 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2016 License: MIT Imports: 13 Imported by: 0

README

gock Build Status GitHub release GoDoc Coverage Status Go Report Card

Versatile HTTP mocking made easy in Go. Heavily inspired by nock.

Take a look to the examples to get started.

Features

  • Simple, expressive, fluent API.
  • Semantic DSL for easy HTTP mocks definition.
  • Built-in helpers for easy JSON/XML mocking.
  • Supports persistent and volatile mocks.
  • Full regexp capable HTTP request matching.
  • Designed for both testing and runtime scenarios.
  • Match request by method, URL params, headers and bodies.
  • Extensible HTTP matching rules.
  • Ability to switch between mock and real networking modes.
  • Ability to filter/map HTTP requests for accurate mock matching.
  • Supports map and filters to handle mocks easily.
  • Wide compatible HTTP interceptor using http.RoundTripper interface.
  • Works with any net/http compatible client, such as gentleman.
  • Network delay simulation (beta).
  • Extensible and hackable API.
  • Dependency free.

Installation

go get -u gopkg.in/h2non/gock.v1

API

See godoc reference for detailed API documentation.

Tips

Testing

Declare your mocks before you start declaring the concrete test logic:

func TestFoo(t *testing.T) {
  defer gock.Off() // Flush pending mocks after test execution

  gock.New("http://server.com").
    Get("/bar").
    Reply(200).
    JSON(map[string]string{"foo": "bar"})

  // Your test code starts here...
}
Race conditions

If you're running concurrent code, be aware that your mocks are declared first to avoid unexpected race conditions while configuring gock or intercepting custom HTTP clients.

gock is not fully thread-safe, but sensible parts are. Any help making gock more reliable in this sense is highly appreciated.

Define complex mocks first

If you're mocking a bunch of mocks in the same test suite, it's recommended to define the more concrete mocks first, and then the generic ones.

This approach usually avoids matching unexpected generic mocks (e.g: specific header, body payload...) instead of the generic ones that performs less complex matches.

Examples

See examples directory for more featured use cases.

Simple mocking via tests
package test

import (
  "github.com/nbio/st"
  "gopkg.in/h2non/gock.v0"
  "io/ioutil"
  "net/http"
  "testing"
)

func TestSimple(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Get("/bar").
    Reply(200).
    JSON(map[string]string{"foo": "bar"})

  res, err := http.Get("http://foo.com/bar")
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)

  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body)[:13], `{"foo":"bar"}`)

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}
Request headers matching
package test

import (
  "github.com/nbio/st"
  "gopkg.in/h2non/gock.v0"
  "io/ioutil"
  "net/http"
  "testing"
)

func TestMatchHeaders(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    MatchHeader("Authorization", "^foo bar$").
    MatchHeader("API", "1.[0-9]+").
    HeaderPresent("Accept").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  req.Header.Set("Authorization", "foo bar")
  req.Header.Set("API", "1.0")
  req.Header.Set("Accept", "text/plain")

  res, err := (&http.Client{}).Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}
JSON body matching and response
package test

import (
  "bytes"
  "github.com/nbio/st"
  "gopkg.in/h2non/gock.v0"
  "io/ioutil"
  "net/http"
  "testing"
)

func TestMockSimple(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Post("/bar").
    Type("json").
    JSON(map[string]string{"foo": "bar"}).
    Reply(201).
    JSON(map[string]string{"bar": "foo"})

  body := bytes.NewBuffer([]byte(`{"foo":"bar"}`))
  res, err := http.Post("http://foo.com/bar", "application/json", body)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 201)

  resBody, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(resBody)[:13], `{"bar":"foo"}`)

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}
Mocking a custom http.Client and http.RoundTripper
package test

import (
  "github.com/nbio/st"
  "gopkg.in/h2non/gock.v0"
  "io/ioutil"
  "net/http"
  "testing"
)

func TestClient(t *testing.T) {
  defer gock.Off()

  gock.New("http://foo.com").
    Reply(200).
    BodyString("foo foo")

  req, err := http.NewRequest("GET", "http://foo.com", nil)
  client := &http.Client{Transport: &http.Transport{}}
  gock.InterceptClient(client)

  res, err := client.Do(req)
  st.Expect(t, err, nil)
  st.Expect(t, res.StatusCode, 200)
  body, _ := ioutil.ReadAll(res.Body)
  st.Expect(t, string(body), "foo foo")

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}
Enable real networking
package main

import (
  "fmt"
  "gopkg.in/h2non/gock.v0"
  "io/ioutil"
  "net/http"
)

func main() {
  defer gock.Off()
  defer gock.DisableNetworking()

  gock.EnableNetworking()
  gock.New("http://httpbin.org").
    Get("/get").
    Reply(201).
    SetHeader("Server", "gock")

  res, err := http.Get("http://httpbin.org/get")
  if err != nil {
    fmt.Errorf("Error: %s", err)
  }

  // The response status comes from the mock
  fmt.Printf("Status: %d\n", res.StatusCode)
  // The server header comes from mock as well
  fmt.Printf("Server header: %s\n", res.Header.Get("Server"))
  // Response body is the original
  body, _ := ioutil.ReadAll(res.Body)
  fmt.Printf("Body: %s", string(body))

  // Verify that we don't have pending mocks
  st.Expect(t, gock.IsDone(), true)
}

Hacking it!

You can easily hack gock defining custom matcher functions with own matching rules.

See add matcher functions and custom matching layer examples for further details.

License

MIT - Tomas Aparicio

Documentation

Index

Constants

View Source
const EOL = 0xa

EOL represents the end of line character.

View Source
const Version = "1.0.0"

Version defines the current package semantic version.

Variables

View Source
var (
	// DefaultTransport stores the default mock transport used by gock.
	DefaultTransport = NewTransport()

	// NativeTransport stores the native net/http default transport
	// in order to restore it when needed.
	NativeTransport = http.DefaultTransport
)
View Source
var BodyTypeAliases = map[string]string{
	"html": "text/html",
	"text": "text/plain",
	"json": "application/json",
	"xml":  "application/xml",
	"form": "multipart/form-data",
	"url":  "application/x-www-form-urlencoded",
}

BodyTypeAliases stores a generic MIME type by alias.

View Source
var BodyTypes = []string{
	"text/html",
	"text/plain",
	"application/json",
	"application/xml",
	"multipart/form-data",
	"application/x-www-form-urlencoded",
}

BodyTypes stores the supported MIME body types for matching. Currently only text-based types.

View Source
var DefaultMatcher = NewMatcher()

DefaultMatcher stores the default Matcher instance used to match mocks.

View Source
var (
	// ErrCannotMatch store the error returned in case of no matches.
	ErrCannotMatch = errors.New("gock: cannot match any request")
)

Matchers stores all the built-in mock matchers.

View Source
var MatchersBody = []MatchFunc{
	MatchBody,
}

MatchersBody exposes an slice of HTTP body specific built-in mock matchers.

MatchersHeader exposes an slice of HTTP header specific mock matchers.

Functions

func Clean

func Clean()

Clean cleans the mocks store removing disabled or obsolete mocks.

func Disable

func Disable()

Disable disables HTTP traffic interception by gock.

func DisableNetworking

func DisableNetworking()

DisableNetworking enables real HTTP networking

func DisableNetworkingFilters

func DisableNetworkingFilters()

DisableNetworkingFilters disables registered networking filters.

func EnableNetworking

func EnableNetworking()

EnableNetworking enables real HTTP networking

func Exists

func Exists(m Mock) bool

Exists checks if the given Mock is already registered.

func Flush

func Flush()

Flush flushes the current stack of registered mocks.

func Intercept

func Intercept()

Intercept enables HTTP traffic interception via http.DefaultTransport. If you are using a custom HTTP transport, you have to use `gock.Transport()`

func InterceptClient

func InterceptClient(cli *http.Client)

InterceptClient allows the developer to intercept HTTP traffic using a custom http.Client who uses a non default http.Transport/http.RoundTripper implementation.

func Intercepting

func Intercepting() bool

Intercepting returns true if gock is currently able to intercept.

func IsDone

func IsDone() bool

IsDone returns true if all the registered mocks has been triggered successfully.

func IsPending

func IsPending() bool

IsPending returns true if there are pending mocks.

func MatchBody

func MatchBody(req *http.Request, ereq *Request) (bool, error)

MatchBody tries to match the request body. TODO: not too smart now, needs several improvements.

func MatchHeaders

func MatchHeaders(req *http.Request, ereq *Request) (bool, error)

MatchHeaders matches the headers fields of the given request.

func MatchHost

func MatchHost(req *http.Request, ereq *Request) (bool, error)

MatchHost matches the HTTP host header field of the given request.

func MatchMethod

func MatchMethod(req *http.Request, ereq *Request) (bool, error)

MatchMethod matches the HTTP method of the given request.

func MatchPath

func MatchPath(req *http.Request, ereq *Request) (bool, error)

MatchPath matches the HTTP URL path of the given request.

func MatchQueryParams

func MatchQueryParams(req *http.Request, ereq *Request) (bool, error)

MatchQueryParams matches the URL query params fields of the given request.

func MatchScheme

func MatchScheme(req *http.Request, ereq *Request) (bool, error)

MatchScheme matches the request URL protocol scheme.

func NetworkingFilter

func NetworkingFilter(fn FilterRequestFunc)

NetworkingFilter determines if an http.Request should be triggered or not.

func Off

func Off()

Off disables the default HTTP interceptors and removes all the registered mocks, even if they has not been intercepted yet.

func Register

func Register(mock Mock)

Register registers a new mock in the current mocks stack.

func Remove

func Remove(m Mock)

Remove removes a registered mock by reference.

func Responder

func Responder(req *http.Request, mock *Response, res *http.Response) (*http.Response, error)

Responder builds a mock http.Response based on the given Response mock.

func RestoreClient

func RestoreClient(cli *http.Client)

RestoreClient allows the developer to disable and restore the original transport in the given http.Client.

Types

type FilterRequestFunc

type FilterRequestFunc func(*http.Request) bool

FilterRequestFunc represents the required function interface for request filters.

type FilterResponseFunc

type FilterResponseFunc func(*http.Response) bool

FilterResponseFunc represents the required function interface impletemed by response filters.

type MapRequestFunc

type MapRequestFunc func(*http.Request) *http.Request

MapRequestFunc represents the required function interface for request mappers.

type MapResponseFunc

type MapResponseFunc func(*http.Response) *http.Response

MapResponseFunc represents the required function interface impletemed by response mappers.

type MatchFunc

type MatchFunc func(*http.Request, *Request) (bool, error)

MatchFunc represents the required function interface implemented by matchers.

type Matcher

type Matcher interface {
	// Get returns a slice of registered function matchers.
	Get() []MatchFunc

	// Add adds a new matcher function.
	Add(MatchFunc)

	// Set sets the matchers functions stack.
	Set([]MatchFunc)

	// Flush flushes the current matchers function stack.
	Flush()

	// Match matches the given http.Request with a mock Request.
	Match(*http.Request, *Request) (bool, error)
}

Matcher represents the required interface implemented by mock matchers.

type Mock

type Mock interface {
	// Disable disables the current mock manually.
	Disable()

	// Done returns true if the current mock is disabled.
	Done() bool

	// Request returns the mock Request instance.
	Request() *Request

	// Response returns the mock Response instance.
	Response() *Response

	// Match matches the given http.Request with the current mock.
	Match(*http.Request) (bool, error)

	// AddMatcher adds a new matcher function.
	AddMatcher(MatchFunc)

	// SetMatcher uses a new matcher implementation.
	SetMatcher(Matcher)
}

Mock represents the required interface that must be implemented by HTTP mock instances.

func GetAll

func GetAll() []Mock

GetAll returns the current stack of registed mocks.

func MatchMock

func MatchMock(req *http.Request) (Mock, error)

MatchMock is a helper function that matches the given http.Request in the list of registered mocks, returning it if matches or error if it fails.

func Pending

func Pending() []Mock

Pending returns an slice of pending mocks.

type MockMatcher

type MockMatcher struct {
	Matchers []MatchFunc
}

MockMatcher implements a mock matcher

func NewBasicMatcher

func NewBasicMatcher() *MockMatcher

NewBasicMatcher creates a new matcher with header only mock matchers.

func NewEmptyMatcher

func NewEmptyMatcher() *MockMatcher

NewEmptyMatcher creates a new empty matcher with out default amtchers.

func NewMatcher

func NewMatcher() *MockMatcher

NewMatcher creates a new mock matcher using the default matcher functions.

func (*MockMatcher) Add

func (m *MockMatcher) Add(fn MatchFunc)

Add adds a new function matcher.

func (*MockMatcher) Flush

func (m *MockMatcher) Flush()

Flush flushes the current matcher

func (*MockMatcher) Get

func (m *MockMatcher) Get() []MatchFunc

Get returns a slice of registered function matchers.

func (*MockMatcher) Match

func (m *MockMatcher) Match(req *http.Request, ereq *Request) (bool, error)

Match matches the given http.Request with a mock request returning true in case that the request matches, otherwise false.

func (*MockMatcher) Set

func (m *MockMatcher) Set(stack []MatchFunc)

Set sets a new stack of matchers functions.

type Mocker

type Mocker struct {
	// contains filtered or unexported fields
}

Mocker implements a Mock capable interface providing a default mock configuration used internally to store mocks.

func NewMock

func NewMock(req *Request, res *Response) *Mocker

NewMock creates a new HTTP mock based on the given request and response instances. It's mostly used internally.

func (*Mocker) AddMatcher

func (m *Mocker) AddMatcher(fn MatchFunc)

AddMatcher adds a new matcher function for the current mock expectation.

func (*Mocker) Disable

func (m *Mocker) Disable()

Disable disables the current mock manually.

func (*Mocker) Done

func (m *Mocker) Done() bool

Done returns true in case that the current mock instance is disabled and therefore must be removed.

func (*Mocker) Match

func (m *Mocker) Match(req *http.Request) (bool, error)

Match matches the given http.Request with the current Request mock expectation, returning true if matches.

func (*Mocker) Request

func (m *Mocker) Request() *Request

Request returns the Request instance configured for the current HTTP mock.

func (*Mocker) Response

func (m *Mocker) Response() *Response

Response returns the Response instance configured for the current HTTP mock.

func (*Mocker) SetMatcher

func (m *Mocker) SetMatcher(matcher Matcher)

SetMatcher sets a new matcher implementation for the current mock expectation.

type Request

type Request struct {
	// Mock stores the parent mock reference for the current request mock used for method delegation.
	Mock Mock

	// Response stores the current Response instance for the current matches Request.
	Response *Response

	// Error stores the latest mock request configuration error.
	Error error

	// Counter stores the pending times that the current mock should be active.
	Counter int

	// Persisted stores if the current mock should be always active.
	Persisted bool

	// URLStruct stores the parsed URL as *url.URL struct.
	URLStruct *url.URL

	// Method stores the Request HTTP method to match.
	Method string

	// Header stores the HTTP header fields to match.
	Header http.Header

	// Cookies stores the Request HTTP cookies values to match.
	Cookies []*http.Cookie

	// BodyBuffer stores the body data to match.
	BodyBuffer []byte

	// Mappers stores the request functions mappers used for matching.
	Mappers []MapRequestFunc

	// Filters stores the request functions filters used for matching.
	Filters []FilterRequestFunc
}

Request represents the high-level HTTP request used to store request fields used to match intercepted requests.

func New

func New(uri string) *Request

New creates and registers a new HTTP mock with default settings and returns the Request DSL for HTTP mock definition and set up.

func NewRequest

func NewRequest() *Request

NewRequest creates a new Request instance.

func (*Request) AddMatcher

func (r *Request) AddMatcher(fn MatchFunc) *Request

AddMatcher adds a new matcher function to match the request.

func (*Request) Body

func (r *Request) Body(body io.Reader) *Request

Body defines the body data to match based on a io.Reader interface.

func (*Request) BodyString

func (r *Request) BodyString(body string) *Request

BodyString defines the body to match based on a given string.

func (*Request) Delete

func (r *Request) Delete(path string) *Request

Delete specifies the DELETE method and the given URL path to match.

func (*Request) EnableNetworking

func (r *Request) EnableNetworking() *Request

EnableNetworking enables the use real networking for the current mock.

func (*Request) File

func (r *Request) File(path string) *Request

File defines the body to match based on the given file path string.

func (*Request) Filter

func (r *Request) Filter(fn FilterRequestFunc) *Request

Filter filters a new request filter function to filter http.Request before the matching process.

func (*Request) Get

func (r *Request) Get(path string) *Request

Get specifies the GET method and the given URL path to match.

func (*Request) Head

func (r *Request) Head(path string) *Request

Head specifies the HEAD method and the given URL path to match.

func (*Request) HeaderPresent

func (r *Request) HeaderPresent(key string) *Request

HeaderPresent defines that a header field must be present in the request.

func (*Request) JSON

func (r *Request) JSON(data interface{}) *Request

JSON defines the JSON body to match based on a given structure.

func (*Request) Map

func (r *Request) Map(fn MapRequestFunc) *Request

Map adds a new request mapper function to map http.Request before the matching process.

func (*Request) MatchHeader

func (r *Request) MatchHeader(key, value string) *Request

MatchHeader defines a new key and value header to match.

func (*Request) MatchHeaders

func (r *Request) MatchHeaders(headers map[string]string) *Request

MatchHeaders defines a map of key-value headers to match.

func (*Request) MatchParam

func (r *Request) MatchParam(key, value string) *Request

MatchParam defines a new key and value URL query param to match.

func (*Request) MatchParams

func (r *Request) MatchParams(params map[string]string) *Request

MatchParams defines a map of URL query param key-value to match.

func (*Request) MatchType

func (r *Request) MatchType(kind string) *Request

MatchType defines the request Content-Type MIME header field. Supports type alias. E.g: json, xml, form, text...

func (*Request) ParamPresent

func (r *Request) ParamPresent(key string) *Request

ParamPresent matches if the given query param key is present in the URL.

func (*Request) Patch

func (r *Request) Patch(path string) *Request

Patch specifies the PATCH method and the given URL path to match.

func (*Request) Path

func (r *Request) Path(path string) *Request

Path defines the mock URL path value to match.

func (*Request) Persist

func (r *Request) Persist() *Request

Persist defines the current HTTP mock as persistent and won't be removed after intercepting it.

func (*Request) Post

func (r *Request) Post(path string) *Request

Post specifies the POST method and the given URL path to match.

func (*Request) Put

func (r *Request) Put(path string) *Request

Put specifies the PUT method and the given URL path to match.

func (*Request) Reply

func (r *Request) Reply(status int) *Response

Reply defines the Response status code and returns the mock Response DSL.

func (*Request) ReplyError

func (r *Request) ReplyError(err error) *Response

ReplyError defines the Response simulated error.

func (*Request) ReplyFunc

func (r *Request) ReplyFunc(replier func(*Response)) *Response

ReplyFunc allows the developer to define the mock response via a custom function.

func (*Request) SetMatcher

func (r *Request) SetMatcher(matcher Matcher) *Request

SetMatcher sets a new matcher function to match the request.

func (*Request) SetURL

func (r *Request) SetURL(u *url.URL) *Request

SetURL defines the url.URL struct to be used for matching.

func (*Request) Times

func (r *Request) Times(num int) *Request

Times defines the number of times that the current HTTP mock should remain active.

func (*Request) URL

func (r *Request) URL(uri string) *Request

URL defines the mock URL to match.

func (*Request) XML

func (r *Request) XML(data interface{}) *Request

XML defines the XML body to match based on a given structure.

type Response

type Response struct {
	// Mock stores the parent mock reference for the current response mock used for method delegation.
	Mock Mock

	// Error stores the latest response configuration or injected error.
	Error error

	// UseNetwork enables the use of real network for the current mock.
	UseNetwork bool

	// StatusCode stores the response status code.
	StatusCode int

	// Headers stores the response headers.
	Header http.Header

	// Cookies stores the response cookie fields.
	Cookies []*http.Cookie

	// BodyBuffer stores the array of bytes to use as body.
	BodyBuffer []byte

	// ResponseDelay stores the simulated response delay.
	ResponseDelay time.Duration

	// Mappers stores the request functions mappers used for matching.
	Mappers []MapResponseFunc

	// Filters stores the request functions filters used for matching.
	Filters []FilterResponseFunc
}

Response represents high-level HTTP fields to configure and define HTTP responses intercepted by gock.

func NewResponse

func NewResponse() *Response

NewResponse creates a new Response.

func (*Response) AddHeader

func (r *Response) AddHeader(key, value string) *Response

AddHeader adds a new header field in the mock response with out removing an existent one.

func (*Response) Body

func (r *Response) Body(body io.Reader) *Response

Body sets the HTTP response body to be used.

func (*Response) BodyString

func (r *Response) BodyString(body string) *Response

BodyString defines the response body as string.

func (*Response) Delay

func (r *Response) Delay(delay time.Duration) *Response

Delay defines the response simulated delay. This feature is still experimental and will be improved in the future.

func (*Response) Done

func (r *Response) Done() bool

Done returns true if the mock was done and disabled.

func (*Response) EnableNetworking

func (r *Response) EnableNetworking() *Response

EnableNetworking enables the use real networking for the current mock.

func (*Response) File

func (r *Response) File(path string) *Response

File defines the response body reading the data from disk based on the file path string.

func (*Response) Filter

func (r *Response) Filter(fn FilterResponseFunc) *Response

Filter filters a new request filter function to filter http.Request before the matching process.

func (*Response) JSON

func (r *Response) JSON(data interface{}) *Response

JSON defines the response body based on a JSON based input.

func (*Response) Map

func (r *Response) Map(fn MapResponseFunc) *Response

Map adds a new response mapper function to map http.Response before the matching process.

func (*Response) SetError

func (r *Response) SetError(err error) *Response

SetError defines the response simulated error.

func (*Response) SetHeader

func (r *Response) SetHeader(key, value string) *Response

SetHeader sets a new header field in the mock response.

func (*Response) SetHeaders

func (r *Response) SetHeaders(headers map[string]string) *Response

SetHeaders sets a map of header fields in the mock response.

func (*Response) Status

func (r *Response) Status(code int) *Response

Status defines the desired HTTP status code to reply in the current response.

func (*Response) Type

func (r *Response) Type(kind string) *Response

Type defines the response Content-Type MIME header field. Supports type alias. E.g: json, xml, form, text...

func (*Response) XML

func (r *Response) XML(data interface{}) *Response

XML defines the response body based on a XML based input.

type Transport

type Transport struct {

	// Transport encapsulates the original http.RoundTripper transport interface for delegation.
	Transport http.RoundTripper
	// contains filtered or unexported fields
}

Transport implements http.RoundTripper, which fulfills single http requests issued by an http.Client.

gock's Transport encapsulates a given or default http.Transport for further delegation, if needed.

func NewTransport

func NewTransport() *Transport

NewTransport creates a new *Transport with no responders.

func (*Transport) CancelRequest

func (m *Transport) CancelRequest(req *http.Request)

CancelRequest is a no-op function.

func (*Transport) RoundTrip

func (m *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip receives HTTP requests and routes them to the appropriate responder. It is required to implement the http.RoundTripper interface. You will not interact with this directly, instead the *http.Client you are using will call it for you.

Directories

Path Synopsis
_examples

Jump to

Keyboard shortcuts

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