mockserver

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

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

Go to latest
Published: Mar 8, 2016 License: MIT Imports: 9 Imported by: 0

README

mockserver

Go Doc

I have seen no good example or explanation on mocking when it comes to doing integration testing. You don't want your tests to always all a third party API or you need to create a mockserver of your API. Either way, the key feature about this mockserver is ROUTING which I went with httprouter because I like speed. There is helper functions to generate one off httptest.Server for JSON and XML as well a simple one.

This merely is exposing the unmodified power of routing from httprouter to testing.

Let's get this party started

Routes (borrowed from the routing tests)
package your_test

import (
	"bytes"
	"fmt"
	"net/http"

	"github.com/apriendeau/mockserver"
	"github.com/stretchr/testify/assert"
)

func sampleRoutes() []mockserver.Route {
	first := mockserver.Route{
		Method: "GET",
		Path:   "/hello/world",
		Handle: httprouter.Handle(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
			w.WriteHeader(200)
			w.Header().Set("Content-Type", "plain/text")
			fmt.Fprint(w, "Hello world")
		}),
	}
	second := mockserver.Route{
		Method: "POST",
		Path:   "/welcome/:name",
		Handle: httprouter.Handle(func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
			w.WriteHeader(200)
			w.Header().Set("Content-Type", "plain/text")
			fmt.Fprint(w, "Welcome ", p.ByName("name"))
		}),
	}
	return []mockserver.Route{first, second}
}

func TestAllTheThings(t *testing) {
	assert := assert.New(t)
	routes := sampleRoutes()
	server := mockserver.WithRoutes(routes)
	defer server.Close()

	resp, err := http.Get(server.URL + "/random")
	assert.NoError(err)
	// This will pass
	assert.Equal(404, resp.StatusCode)

	// How about some parameters
	resp, err = http.Post(server.URL+"/welcome/tony", "plain/text", bytes.NewBuffer([]byte{}))
	assert.NoError(err)
	assert.Equal(200, resp.StatusCode)
	body, err := parseResp(resp.Body)
	assert.NoError(err)
	assert.Equal(body, "Welcome tony") // Booyah biz-nitches

	// How about the same route but an umplemented method?
	resp, err = http.Get(server.URL + "/welcome/tony")
	assert.NoError(err)
	assert.Equal(405, resp.StatusCode) // again, booyah.
}
FAQs

Q. Can you create more than one server in a function?

A. Yes, you can because mockserver is just riding on top of httptest.Server. This also prevents url and port collisions so you can spin up several different mocks for you.

Q. Why do I have to close the server?

A. mockserver cannot predict when you are done with your tests so you can defer or you can close at the end since this is just helper functions around httptest.

Q. What sparked the desire?

A. Well, integration/functional testing when building a PaaS service on top of Mesosphere is rather annoying and slow to spin up several docker containers with each service so now, I can create mocks of those APIs with ease.

Q. Can I use an existing router?

A. Yes, you can if it implements http.Handle interface. Here is an example using httprouter.

mockserver.HandlerFunc(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
	router := httprouter.New()
	router.ServerHTTP(w,r)
}))

Contributing

Feel free to create issues and PRs. All is welcome.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func HandlerFunc

func HandlerFunc(fn http.HandlerFunc) *httptest.Server

HandlerFunc takes a http.HandlerFunc instead of a body so you can do whatever that you would like and take full control

func JSON

func JSON(code int, body interface{}) (*httptest.Server, error)

JSON does a little more magic, where it takes a code and interface{}. It will set the content-type to application/json for you and marshal the object for the test server

func Simple

func Simple(code int, contentType, body string) *httptest.Server

Simple does little to no setup for you just takes status code, content-type and the body

func WithRoutes

func WithRoutes(rtes []Route) *httptest.Server

WithRoutes creates a new mockserver that takes an array of routes and puts them into a httptest.Server

func XML

func XML(code int, body interface{}) (*httptest.Server, error)

XML does a little more magic, where it takes a code and interface{}. It will set the content-type to text/xml for you and marshal the object for the test server

Types

type Route

type Route struct {
	Method string
	Path   string
	Handle httprouter.Handle
}

Route is common structure for setting up routes with the mockserver

type Template

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

Template is exported for the sake of name collision and name spacing.

func NewTemplate

func NewTemplate(name, base string) (*Template, error)

NewTemplate sets up test/template. It is if you want to dynamically populate your response. The base just is the text/template syntax

func (*Template) Server

func (t *Template) Server(code int, contentType string, obj interface{}) *httptest.Server

Server creates an httptest.Server for you. If your template fails with the provided object, the http server will return a 500, set the content-type to plain/text and the error will be written since it happens at the time of execution

Jump to

Keyboard shortcuts

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