A simple and extensible behavioural testing library in golang. Supports mocking external http calls and renders sequence diagrams on completion.
In behavioural tests the internal structure of the app is not known by the tests. Data is input to the system and the outputs are expected to meet certain conditions.
Logo by @egonelbre
Please visit https://apitest.dev for the latest documentation.
go get -u github.com/steinfletcher/apitest
Example | Comment |
---|---|
gin | popular martini-like web framework |
gorilla | the gorilla web toolkit |
iris | iris web framework |
echo | High performance, extensible, minimalist Go web framework |
mocks | example mocking out external http calls |
sequence diagrams | generate sequence diagrams from tests. See the demo |
Library | Comment |
---|---|
JSONPath | JSONPath assertion addons |
PlantUML | Export sequence diagrams as plantUML |
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/user/1234").
Expect(t).
Body(`{"id": "1234", "name": "Tate"}`).
Status(http.StatusCreated).
End()
}
For asserting on parts of the response body JSONPath may be used. A separate module must be installed which provides these assertions - go get -u github.com/steinfletcher/apitest-jsonpath
. This is packaged separately to keep this library dependency free.
Given the response is {"a": 12345, "b": [{"key": "c", "value": "result"}]}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
Expect(t).
Assert(jsonpath.Contains(`$.b[? @.key=="c"].value`, "result")).
End()
}
and jsonpath.Equals
checks for value equality
func TestApi(t *testing.T) {
apitest.New(handler).
Get("/hello").
Expect(t).
Assert(jsonpath.Equal(`$.a`, float64(12345))).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
Expect(t).
Assert(func(res *http.Response, req *http.Request) {
assert.Equal(t, http.StatusOK, res.StatusCode)
}).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Patch("/hello").
Expect(t).
Status(http.StatusOK).
Cookies(apitest.Cookie"ABC").Value("12345")).
CookiePresent("Session-Token").
CookieNotPresent("XXX").
Cookies(
apitest.Cookie("ABC").Value("12345"),
apitest.Cookie("DEF").Value("67890"),
).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
Expect(t).
Status(http.StatusOK).
Headers(map[string]string{"ABC": "12345"}).
End()
}
var getUser = apitest.NewMock().
Get("/user/12345").
RespondWith().
Body(`{"name": "jon", "id": "1234"}`).
Status(http.StatusOK).
End()
var getPreferences = apitest.NewMock().
Get("/preferences/12345").
RespondWith().
Body(`{"is_contactable": true}`).
Status(http.StatusOK).
End()
func TestApi(t *testing.T) {
apitest.New().
Mocks(getUser, getPreferences).
Handler(handler).
Get("/hello").
Expect(t).
Status(http.StatusOK).
Body(`{"name": "jon", "id": "1234"}`).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Report(apitest.SequenceDiagram()).
Mocks(getUser, getPreferences).
Handler(handler).
Get("/hello").
Expect(t).
Status(http.StatusOK).
Body(`{"name": "jon", "id": "1234"}`).
End()
}
It is possible to override the default storage location by passing the formatter instance Report(apitest.NewSequenceDiagramFormatter(".sequence-diagrams"))
.
You can bring your own formatter too if you want to produce custom output. By default a sequence diagram is rendered on a html page. See the demo
func TestApi(t *testing.T) {
apitest.New().
Debug().
Handler(handler).
Get("/hello").
Expect(t).
Status(http.StatusOK).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
BasicAuth("username:password").
Expect(t).
Status(http.StatusOK).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
Cookies(apitest.Cookie("ABC").Value("12345")).
Expect(t).
Status(http.StatusOK).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Delete("/hello").
Headers(map[string]string{"My-Header": "12345"}).
Expect(t).
Status(http.StatusOK).
End()
}
Query
, QueryParams
and QueryCollection
can all be used in combination
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
QueryParams(map[string]string{"a": "1", "b": "2"}).
Query("c", "d").
Expect(t).
Status(http.StatusOK).
End()
}
Providing {"a": {"b", "c", "d"}
results in parameters encoded as a=b&a=c&a=d
.
QueryCollection
can be used in combination with Query
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Get("/hello").
QueryCollection(map[string][]string{"a": {"b", "c", "d"}}).
Expect(t).
Status(http.StatusOK).
End()
}
func TestApi(t *testing.T) {
apitest.New().
Observe(func(res *http.Response, req *http.Request, apiTest *apitest.APITest) {
// do something with res and req
}).
Handler(handler).
Get("/hello").
Expect(t).
Status(http.StatusOK).
End()
}
This is useful for mutating the request before it is sent to the system under test.
func TestApi(t *testing.T) {
apitest.New().
Handler(handler).
Intercept(func(req *http.Request) {
req.URL.RawQuery = "a[]=xxx&a[]=yyy"
}).
Get("/hello").
Expect(t).
Status(http.StatusOK).
End()
}
View the contributing guide.