Skip to content

Fake endpoints (fakepoints) for HTTP testing. Specify the response data sent back.

Notifications You must be signed in to change notification settings

nicholasf/fakepoint

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fakepoint

Fakepoint - Fake Endpoint

Create Fake endpoints for HTTP testing. Specify the response data sent back.

Godocs

Install

go get github.com/nicholasf/fakepoint

Tests

go test

Changelog

  • 324780a16382aa8f390ed549e81c79a3a7048af9 (3/1/15)

Breaking change to previous DSL. The maker now uses NewGet instead of PlanGet. Fakepoints can now be given files or strings for response data - SetResponse or SetResponseDocument.

Example

Use it to simulate a third party API in your tests.

maker := NewFakepointMaker()
maker.NewGet("https://api.opsgenie.com/v1/json/alert", 200).SetResponse(`{ "code": 200 }`).SetHeader("Content-Type", "application/json")
resp, _ := maker.Client().Get("https://api.opsgenie.com/v1/json/alert")

Rationale

After looking at httptest.ResponseRecorder I decided it was a bit verbose. I wanted a tidier DSL similar to Fakeweb and nock.

I based my approach about the http.Client. The Fakepoint maker lets you stub URLs then calling maker.Client() returns a standard client to use.

From here you can execute a request by running a HTTP verb function call on the client:

maker.NewGet("http://abc.com", 200).SetResponse("")
resp, err := maker.Client().Get("http://abc.com")

Or passing in a request to client.Do(req):

maker.NewGet("http://example.com", 200).SetResponse("")
req, err := http.NewRequest("GET", "http://example.com", nil)
resp, err := maker.Client().Do(req)

How to use

First, set up the FakepointMaker.

maker := NewFakepointMaker()

From here, set up an endpoint with maker.NewGet, maker.NewPost, maker.NewPut, or maker.NewDelete. Also specify the http status code you expect.

fakepoint := maker.NewGet("https://api.opsgenie.com/v1/json/alert", 200)

Response data to be returned may be set with one of two methods on the fakepoint; SetResponse(..) or SetResponseDocument(..):

	fakepoint.SetResponse(`{ "code": 200 }`) //response uses the a string
	fakepoint.SetResponseDocument("./response.json") //response loads the file using ioutil.ReadFile

Note, that Fakepoints uses chaining. So you could've just written maker.NewGet("https://api.opsgenie.com/v1/json/alert", 200).SetResponse(`{ "code": 200 }`)

This is, perhaps, unidiomatic Golang; in hindsight the Must pattern would have been more appropriate. C'est la vie.

You can chain further calls to set headers and increase the frequency of the endpoint:

trip := maker.NewGet("https://api.opsgenie.com/v1/json/alert", 200)
trip.SetResponse(`{ "code": 200 }`).SetHeader("Content-Type", "application/json").Duplicate(1)

Fakepoints only have a lifetime of one request unless Duplicate is used to specify additional call lifetimes.

This call sets the Content-Type in the response header, and increases the amount of times the client will field this request by 1.

Finally, get the http.Client from the FakepointMaker:

client := maker.Client()

This is the regular golang http.Client, with the Roundtripper Transport swapped out to something that can facilitate the test.

Fakepoint will cleanly handle 302s by following redirects, and supplying a 'new-location' resource to automate the follows.

Mostly written in Santa Monica, L.A., 2014, while working for Rockpool Labs.

##FAQs

"What's the benefit of fakepoint over http://golang.org/pkg/net/http/httptest?"

The httptest package provides an easy to set up HTTP server for testing and a ResponseRecorder.

I wanted something different: to specify particular URLs, and to write tests to assert that they were called. With the HTTP Server I couldn't specify the URL and with the ResponseRecorder I had to implement a HTTP handler, etc..

I've used tools like nock, fakeweb, etc. in other languages and I wanted something similar.

In particular, I see myself writing a lot of integration code against 3rd party HTTP services, and I want a nice DSL in my tests to prove my code works. All I have to do is expose the call to the client and it's suddenly very testable:

package notifications_test

import (
	. "github.com/smartystreets/goconvey/convey"
	"testing"
	"github.com/nicholasf/fakepoint"
	"allocation/notifications"
)

func TestOpsgenie(t *testing.T) {
	Convey("An Error log is sent to the notifier", t, func() {
		maker := fakepoint.NewFakepointMaker()
		maker.NewPost("https://api.opsgenie.com/v1/json/alert", 200).SetResponse(`{ "code": 200 }`)
		resp, err := notifications.Requester(*maker.Client(), ("https://api.opsgenie.com/v1/json/alert"), []byte(``))
		So(err, ShouldBeNil)
		So(resp.StatusCode, ShouldEqual, 200)
	})
}

"Can I do transfer-coding = "chunked" and get nice responses?"

Not yet, but that'd be grand. I might get around to it if I ever need it.

License

MIT

About

Fake endpoints (fakepoints) for HTTP testing. Specify the response data sent back.

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages