httpstub provides router ( http.Handler
), server ( *httptest.Server
) and client ( *http.Client
) for stubbing, for testing in Go.
There is an gRPC version stubbing tool with the same design concept, grpcstub.
package myapp
import (
"io"
"net/http"
"testing"
"github.com/k1LoW/httpstub"
)
func TestGet(t *testing.T) {
ts := httpstub.NewServer(t)
t.Cleanup(func() {
ts.Close()
})
ts.Method(http.MethodGet).Path("/api/v1/users/1").Header("Content-Type", "application/json").ResponseString(http.StatusOK, `{"name":"alice"}`)
res, err := http.Get(ts.URL + "/api/v1/users/1")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
res.Body.Close()
})
body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatal(err)
}
got := string(body)
want := `{"name":"alice"}`
if got != want {
t.Errorf("got %v\nwant %v", got, want)
}
if len(ts.Requests()) != 1 {
t.Errorf("got %v\nwant %v", len(ts.Requests()), 1)
}
}
or
package myapp
import (
"io"
"net/http"
"testing"
"github.com/k1LoW/httpstub"
)
func TestGet(t *testing.T) {
r := httpstub.NewRouter(t)
r.Method(http.MethodGet).Path("/api/v1/users/1").Header("Content-Type", "application/json").ResponseString(http.StatusOK, `{"name":"alice"}`)
ts := r.Server()
t.Cleanup(func() {
ts.Close()
})
res, err := http.Get(ts.URL + "/api/v1/users/1")
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() {
res.Body.Close()
})
body, err := io.ReadAll(res.Body)
if err != nil {
t.Fatal(err)
}
got := string(body)
want := `{"name":"alice"}`
if got != want {
t.Errorf("got %v\nwant %v", got, want)
}
if len(r.Requests()) != 1 {
t.Errorf("got %v\nwant %v", len(r.Requests()), 1)
}
}
httpstub can return responses using examples:
of OpenAPI Document.
ts := httpstub.NewServer(t, httpstub.OpenApi3("path/to/schema.yml"))
t.Cleanup(func() {
ts.Close()
})
ts.ResponseExample()
ts := httpstub.NewServer(t, httpstub.OpenApi3("path/to/schema.yml"))
t.Cleanup(func() {
ts.Close()
})
ts.Method(http.MethodGet).Path("/api/v1/users/1").ResponseExample()
It is possible to specify status codes using wildcard.
ts := httpstub.NewServer(t, httpstub.OpenApi3("path/to/schema.yml"))
t.Cleanup(func() {
ts.Close()
})
ts.Method(http.MethodPost).Path("/api/v1/users").ResponseExample(httpstub.Status("2*"))
It is possible to create a client that will always make an HTTP request to the stub server.
ts := httpstub.NewServer(t)
t.Cleanup(func() {
ts.Close()
})
ts.Method(http.MethodGet).Path("/api/v1/users/1").Header("Content-Type", "application/json").ResponseString(http.StatusOK, `{"name":"alice"}`)
tc := ts.Client()
res, err := tc.Get("https://example.com/api/v1/users/1") // Request goes to stub server instead of https://example.com
if err != nil {
t.Fatal(err)
}
package client_test
import (
"net/http"
"testing"
"github.com/k1LoW/httpstub"
twilio "github.com/twilio/twilio-go"
twclient "github.com/twilio/twilio-go/client"
api "github.com/twilio/twilio-go/rest/api/v2010"
)
func TestTwilioClient(t *testing.T) {
r := httpstub.NewRouter(t)
r.Method(http.MethodPost).Path("/2010-04-01/Accounts/*/Messages.json").ResponseString(http.StatusCreated, `{"status":"sending"}`)
ts := r.Server()
t.Cleanup(func() {
ts.Close()
})
tc := ts.Client()
accountSid := "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
authToken := "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"
client := twilio.NewRestClientWithParams(twilio.ClientParams{
Client: &twclient.Client{
Credentials: twclient.NewCredentials(accountSid, authToken),
HTTPClient: tc,
},
})
params := &api.CreateMessageParams{}
params.SetTo("08000000000")
params.SetFrom("05000000000")
params.SetBody("Hello there")
res, err := client.ApiV2010.CreateMessage(params)
if err != nil {
t.Error(err)
}
got := res.Status
want := "sending"
if *got != want {
t.Errorf("got %v\nwant %v", *got, want)
}
}
- github.com/jharlap/httpstub: Easy stub HTTP servers for testing in Go