Skip to content

Commit

Permalink
Merge pull request #2 from erutherford/add-assertions
Browse files Browse the repository at this point in the history
Adds Request Assertions for http fake
  • Loading branch information
maxcnunes authored Jun 11, 2020
2 parents c07c10a + 77b0111 commit c8179db
Show file tree
Hide file tree
Showing 8 changed files with 861 additions and 1 deletion.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ See [Releases](https://github.com/maxcnunes/httpfake/releases) for detailed hist

See [godoc reference](https://godoc.org/github.com/maxcnunes/httpfake) for detailed API documentation.

## Assertions

There are built-in methods you can use to make assertions about requests to your HTTP handlers. The currently
supported assertions are:

* Presence of query parameters
* Query parameter and its expected value
* Presence of HTTP headers
* HTTP header and its expected value
* The expected body of your request

[WithTesting](https://godoc.org/github.com/maxcnunes/httpfake#WithTesting) **must** be provided as a server
option when creating the test server if intend to set request assertions. Failing to set the option
when using request assertions will result in a panic.

### Custom Assertions

You can also provide your own request assertions by creating a type that implements the
[Assertor interface](https://godoc.org/github.com/maxcnunes/httpfake#Assertor). The `Assertor.Log` method will be
called for each assertion before it's processed. The `Assertor.Error` method will only be called if the
`Assertor.Assert` method returns an error.

## Examples

For a full list of examples please check out the [functional_tests folder](/functional_tests).
Expand Down
170 changes: 170 additions & 0 deletions assertions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package httpfake

import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"strings"
"testing"
)

const assertErrorTemplate = "assertion error: %s"

// Assertor provides an interface for setting assertions for http requests
type Assertor interface {
Assert(r *http.Request) error
Log(t testing.TB)
Error(t testing.TB, err error)
}

// requiredHeaders provides an Assertor for the presence of the provided http header keys
type requiredHeaders struct {
Keys []string
}

// Assert runs the required headers assertion against the provided request
func (h *requiredHeaders) Assert(r *http.Request) error {
var missingHeaders []string

for _, key := range h.Keys {
if value := r.Header.Get(key); len(value) == 0 {
missingHeaders = append(missingHeaders, key)
}
}

if len(missingHeaders) > 0 {
return fmt.Errorf("missing required header(s): %s", strings.Join(missingHeaders, ", "))
}

return nil
}

// Log prints a testing info log for the requiredHeaders Assertor
func (h *requiredHeaders) Log(t testing.TB) {
t.Log("Testing request for required headers")
}

// Error prints a testing error for the requiredHeaders Assertor
func (h *requiredHeaders) Error(t testing.TB, err error) {
t.Errorf(assertErrorTemplate, err)
}

// requiredHeaderValue provides an Assertor for a header and its expected value
type requiredHeaderValue struct {
Key string
ExpectedValue string
}

// Assert runs the required header value assertion against the provided request
func (h *requiredHeaderValue) Assert(r *http.Request) error {
if value := r.Header.Get(h.Key); value != h.ExpectedValue {
return fmt.Errorf("header %s does not have the expected value; expected %s to equal %s",
h.Key,
value,
h.ExpectedValue)
}

return nil
}

// Log prints a testing info log for the requiredHeaderValue Assertor
func (h *requiredHeaderValue) Log(t testing.TB) {
t.Logf("Testing request for required header value [%s: %s]", h.Key, h.ExpectedValue)
}

// Error prints a testing error for the requiredHeaderValue Assertor
func (h *requiredHeaderValue) Error(t testing.TB, err error) {
t.Errorf(assertErrorTemplate, err)
}

// requiredQueries provides an Assertor for the presence of the provided query parameter keys
type requiredQueries struct {
Keys []string
}

// Assert runs the required queries assertion against the provided request
func (q *requiredQueries) Assert(r *http.Request) error {
queryVals := r.URL.Query()
var missingParams []string

for _, key := range q.Keys {
if value := queryVals.Get(key); len(value) == 0 {
missingParams = append(missingParams, key)
}
}
if len(missingParams) > 0 {
return fmt.Errorf("missing required query parameter(s): %s", strings.Join(missingParams, ", "))
}

return nil
}

// Log prints a testing info log for the requiredQueries Assertor
func (q *requiredQueries) Log(t testing.TB) {
t.Log("Testing request for required query parameters")
}

// Error prints a testing error for the requiredQueries Assertor
func (q *requiredQueries) Error(t testing.TB, err error) {
t.Errorf(assertErrorTemplate, err)
}

// requiredQueryValue provides an Assertor for a query parameter and its expected value
type requiredQueryValue struct {
Key string
ExpectedValue string
}

// Assert runs the required query value assertion against the provided request
func (q *requiredQueryValue) Assert(r *http.Request) error {
if value := r.URL.Query().Get(q.Key); value != q.ExpectedValue {
return fmt.Errorf("query %s does not have the expected value; expected %s to equal %s", q.Key, value, q.ExpectedValue)
}
return nil
}

// Log prints a testing info log for the requiredQueryValue Assertor
func (q *requiredQueryValue) Log(t testing.TB) {
t.Logf("Testing request for required query parameter value [%s: %s]", q.Key, q.ExpectedValue)
}

// Error prints a testing error for the requiredQueryValue Assertor
func (q *requiredQueryValue) Error(t testing.TB, err error) {
t.Errorf(assertErrorTemplate, err)
}

// requiredBody provides an Assertor for the expected value of the request body
type requiredBody struct {
ExpectedBody []byte
}

// Assert runs the required body assertion against the provided request
func (b *requiredBody) Assert(r *http.Request) error {
if r.Body == nil {
return fmt.Errorf("error reading the request body; the request body is nil")
}

body, err := ioutil.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("error reading the request body: %w", err)
}

if !bytes.EqualFold(b.ExpectedBody, body) {
return fmt.Errorf("request body does not have the expected value; expected %s to equal %s",
string(body[:]),
string(b.ExpectedBody[:]))
}

return nil
}

// Log prints a testing info log for the requiredBody Assertor
func (b *requiredBody) Log(t testing.TB) {
t.Log("Testing request for required a required body")
}

// Error prints a testing error for the requiredBody Assertor
func (b *requiredBody) Error(t testing.TB, err error) {
t.Errorf(assertErrorTemplate, err)
}
Loading

0 comments on commit c8179db

Please sign in to comment.