mockhttp

package module
v0.0.0-...-fa50851 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2018 License: MIT Imports: 10 Imported by: 0

README

mockhttp Documentations Travis CI results GoCover.io

A bare minimal implementation for mocking http.RoundTripper (i.e. any http traffic response).

License

This library is license under the MIT License agreement. You can find a copy of the license within the repository here.

Documentation

Overview

Package mockhttp helps you to mock network behaviour for testing against http stack.

Basic Usage

To mock the transport for whatever test you want to run with "http" library, you may override the response with some of the utils like mockhttp.StaticResponseRT:

mocktransport := mockhttp.StaticResponseRT("hello world", "text/plain")
mockhttp.UseTransport(mocktransport)

...

// resp.Body will always be "hello world", no matter the URL or method
resp, err := http.Get("http://whatever.com")
...

mochhttp.RestoreTransport()

// resp.Body will be normal
resp, err := http.Get("http://whatever.com")

...

Override Multiple Sites Behaviour

You may mux different response for different URL host name.

mux := mockhttp.MuxRoundTripper{}
mux.AddFunc("www.google.com",
	mockhttp.StaticResponseRT("fake google", "text/plain"))
mux.AddFunc("www.facebook.com",
	mockhttp.StaticResponseRT("fake facebook", "text/plain"))

// "*" for setting fallback http.RoundTripper
mux.AddFunc("*", mockhttp.TransportErrorRT(fmt.Errorf("no connection to host")))

mockhttp.UseTransport(mocktransport)

...

// resp.Body will be "fake google"
resp, err := http.Get("http://www.google.com/helloAPI")

// resp.Body will be "fake facebook"
resp, err := http.Get("http://www.facebook.com/helloAPI")

// will always return error: "no connection to host"
resp, err := http.Get("http://www.archive.org/helloAPI")

...

mochhttp.RestoreTransport()

Use Without Overriding DefaultTransport

MuxRoundTripper also can be used directly to create client.

mux := mockhttp.MuxRoundTripper{}
...
mux.GetClient().Post("http://foobar.com", strings.NewReader("some+data"))

Partial Override

You can partially override the round trip like this:

mux := mockhttp.MuxRoundTripper{}
mux.AddFunc("www.google.com",
	mockhttp.StaticResponseRT("fake google", "text/plain"))
mux.AddFunc("www.facebook.com",
	mockhttp.StaticResponseRT("fake facebook", "text/plain"))

// "*" for setting fallback http.RoundTripper
mux.Add("*", http.DefaultTransport)

client := mux.GetClient()
...

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func RestoreTransport

func RestoreTransport()

RestoreTransport restore the http.DefaultTransport to the one before last call of UseTransport().

func UseTransport

func UseTransport(rt http.RoundTripper)

UseTransport use the given roundtripper as the http.DefaultTransport, and store away the current http.DefaultTransport for restoration.

Example (Simple)
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {
	mock := mockhttp.StaticResponseRT("hello world", "text/plain")
	mockhttp.UseTransport(&mock)

	resp, _ := http.Get("https://www.google.com")
	content, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("%s", content)

	mockhttp.RestoreTransport()

}
Output:

hello world

Types

type Middleware

type Middleware interface {
	Wrap(http.RoundTripper) http.RoundTripper
}

Middleware warps an http.RoundTripper and modify the input / output behaviour.

func Chain

func Chain(middlewares ...Middleware) Middleware

Chain wraps the middlware, from outter-most to inner-most, into a combined middleware.

func UseResponseModifier

func UseResponseModifier(modifiers ...ResponseModifier) Middleware

UseResponseModifier converts a function / multiple functions that fulfills ResponseModifier signature into one Middleware.

If more that 1 modifer is provided, they will be chained from first to last. That means the response and error of inner http.RoundTripper will be the input of the first modifer. Then the output of first modifier will be input of the second modifer. So on and so forth until last one.

type MiddlewareFunc

type MiddlewareFunc func(http.RoundTripper) http.RoundTripper

MiddlewareFunc turns a simple function value into Middleware implementation.

func (MiddlewareFunc) Wrap

Wrap implements Middleware

type MuxRoundTripper

type MuxRoundTripper map[string]http.RoundTripper

MuxRoundTripper mux http.RoundTripper by the request's URL.Host field

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	"github.com/yookoala/mockhttp"
)

func main() {

	// a mock transport layer for testing your API calls / resource download
	mock := mockhttp.NewMuxRoundTripper()
	mock.Add("api.service1.com", mockhttp.StaticResponseRT(`{"status": "OK", "cool": true}`, "application/json"))
	mock.Add("api.service2.com", mockhttp.StaticResponseRT(`{"status": "OK", "cool": true}`, "application/json"))
	mock.Add("api.service3.com", mockhttp.ServerErrorRT(http.StatusInternalServerError))
	mock.Add("mycdn-service.com", mockhttp.FileSystemRT("./testdata"))
	mock.Add("*", mockhttp.TransportErrorRT(fmt.Errorf("no network"))) // as fallback

	// simply produces http.Client with the MuxRoundTripper as transport
	client := mock.NewClient()

	var resp *http.Response
	var body []byte
	var err error

	// ordinary http.NewRequest routine
	req, _ := http.NewRequest("GET", "https://api.service1.com/some/endpoint", nil)
	resp, _ = client.Do(req)
	body, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 1 - %s\n", body)

	// directly use http.Client methods
	resp, _ = client.Get("https://api.service1.com/some/endpoint")
	body, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 2 - %s\n", body)

	// POST with http.Client method
	resp, _ = client.Post("https://api.service2.com/some/endpoint", "application/json", strings.NewReader(`{"submit": true}`))
	body, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 3 - %s\n", body)

	// POST to an endpoint with mock server error
	resp, _ = client.Post("https://api.service3.com/some/endpoint", "application/json", strings.NewReader(`{"submit": true}`))
	body, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 4 - %s\n", body)

	// GET a text file, in local file system, with content "hello world"
	resp, _ = client.Get("https://mycdn-service.com/test.txt")
	body, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 5 - %s\n", body)

	// GET an external service with mock transport,
	// which will be handled by "*" host handler.
	_, err = client.Get("https://api.google.com/some/endpoint")
	fmt.Printf("result 6 - %s\n", err.Error())

}
Output:

result 1 - {"status": "OK", "cool": true}
result 2 - {"status": "OK", "cool": true}
result 3 - {"status": "OK", "cool": true}
result 4 - Internal Server Error
result 5 - hello world
result 6 - Get https://api.google.com/some/endpoint: no network

func NewMuxRoundTripper

func NewMuxRoundTripper() MuxRoundTripper

NewMuxRoundTripper returns a new NewMuxRoundTripper

func (MuxRoundTripper) Add

func (mux MuxRoundTripper) Add(host string, rt http.RoundTripper)

Add an http.RoundTripper to the mux with reference to the host. Please note that a fallback http.RoundTripper can be set with host = "*"

func (MuxRoundTripper) AddFunc

func (mux MuxRoundTripper) AddFunc(host string, fn RoundTripperFunc)

AddFunc add an RoundTripperFunc to the mux with reference to the host Please note that a fallback http.RoundTripper can be set with host = "*"

func (MuxRoundTripper) Get

func (mux MuxRoundTripper) Get(host string) (http.RoundTripper, error)

Get the http.RoundTripper for the given host

func (MuxRoundTripper) NewClient

func (mux MuxRoundTripper) NewClient() *http.Client

NewClient returns a new http.Client with the mux as transport

func (MuxRoundTripper) RoundTrip

func (mux MuxRoundTripper) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper

type ResponseModifier

type ResponseModifier func(resp *http.Response, err error) (*http.Response, error)

ResponseModifier implements Middleware by modifying http.Response and/or error output of inner http.RoundTripper output

func ResponseAddHeader

func ResponseAddHeader(key, value string) ResponseModifier

ResponseAddHeader adds the response, if presents, header with given key-value pair

func ResponseSetHeader

func ResponseSetHeader(key, value string) ResponseModifier

ResponseSetHeader sets the response, if presents, header with given key-value pair

func ResponseSetStatus

func ResponseSetStatus(status int) ResponseModifier

ResponseSetStatus sets the response, if presents, status code to the given status

func (ResponseModifier) Wrap

func (modifier ResponseModifier) Wrap(inner http.RoundTripper) http.RoundTripper

Wrap implements Middleware

type RoundTripperFunc

type RoundTripperFunc func(*http.Request) (*http.Response, error)

RoundTripperFunc is a simplified way to implement http.RoundTripper

func FileSystemRT

func FileSystemRT(root string) RoundTripperFunc

FileSystemRT implements http.RoundTripper by returning contents of files in a given folder (as defined as `root`).

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {
	client := &http.Client{
		Transport: mockhttp.FileSystemRT("./testdata"),
	}

	resp, _ := client.Get("https://www.google.com/persons/2.json")
	content, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("result 1: %s\n", content)

	resp, _ = client.Get("https://www.facebook.com/persons/")
	content, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 2: %s\n", content)

}
Output:

result 1: Not Found
result 2: Forbidden

func HandlerRT

func HandlerRT(handler http.Handler) RoundTripperFunc

HandlerRT directly inject an http.Handler to the RoundTripper. You may directly test your handler in this mocked transport.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {

	// some http.Handler you want to test with
	handler := http.NewServeMux()
	handler.HandleFunc("/item/1", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, "content of item 1")
	})
	handler.HandleFunc("/item/", func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusForbidden)
		fmt.Fprint(w, http.StatusText(http.StatusForbidden))
	})

	client := &http.Client{
		Transport: mockhttp.HandlerRT(handler),
	}

	resp, _ := client.Get("https://something.com/item/1")
	content, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("result 1: %s\n", content)

	resp, _ = client.Get("https://something.com/item/2")
	content, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 2: %s\n", content)

}
Output:

result 1: content of item 1
result 2: Forbidden

func ServerErrorRT

func ServerErrorRT(status int) RoundTripperFunc

ServerErrorRT always return a server response of the supplied status code with nil error.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {

	client := &http.Client{
		Transport: mockhttp.ServerErrorRT(http.StatusForbidden),
	}

	resp, _ := client.Get("https://www.google.com")
	content, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("result 1: %s\n", content)

	resp, _ = client.Get("https://www.facebook.com")
	content, _ = ioutil.ReadAll(resp.Body)
	fmt.Printf("result 2: %s\n", content)

}
Output:

result 1: Forbidden
result 2: Forbidden

func StaticResponseRT

func StaticResponseRT(content, contentType string) RoundTripperFunc

StaticResponseRT returns an http.RoundTripper that returns the same response body no matter what the request is.

Example
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {
	client := &http.Client{
		Transport: mockhttp.StaticResponseRT("hello world", "text/plain"),
	}

	resp, _ := client.Get("http://whatever.com")
	content, _ := ioutil.ReadAll(resp.Body)
	fmt.Printf("%s\n", content)

}
Output:

hello world

func TransportErrorRT

func TransportErrorRT(err error) RoundTripperFunc

TransportErrorRT always return nil server response wtih the supplied error

Example
package main

import (
	"fmt"
	"net/http"

	"github.com/yookoala/mockhttp"
)

func main() {
	client := &http.Client{
		Transport: mockhttp.TransportErrorRT(fmt.Errorf("domain not found")),
	}

	_, err := client.Get("https://www.google.com")
	fmt.Printf("result 1: %s\n", err.Error())

	_, err = client.Post("https://www.facebook.com", "text/plain", nil)
	fmt.Printf("result 2: %s\n", err.Error())

}
Output:

result 1: Get https://www.google.com: domain not found
result 2: Post https://www.facebook.com: domain not found

func (RoundTripperFunc) RoundTrip

func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip implements http.RoundTripper

Jump to

Keyboard shortcuts

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