-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
assert: Add HTTP builder to combine request x response using builder. #1491
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import ( | |
"net/http" | ||
"net/http/httptest" | ||
"net/url" | ||
"reflect" | ||
"strings" | ||
) | ||
|
||
|
@@ -163,3 +164,55 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url strin | |
|
||
return !contains | ||
} | ||
|
||
// HTTP asserts that a specfied handler returns set of expected values given by HttpOptions. | ||
// | ||
// assert.HTTP(t, myHandler, "www.google.com", nil, WithCode(200), WithBody("I'm Feeling Lucky"), WithRequestHeader(http.Header{"a": []string{"b"}}, WithExpectedBody(bytes.NewBuffer("c")))) | ||
// | ||
// Returns whether the assertion was successful (true) or not (false). | ||
func HTTP(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, options ...HttpOption) bool { | ||
if h, ok := t.(tHelper); ok { | ||
h.Helper() | ||
} | ||
|
||
if options == nil { | ||
Fail(t, fmt.Sprintf("No options selected, no assertions can be executed")) | ||
return false | ||
} | ||
|
||
b := &builder{} | ||
for _, option := range options { | ||
err := option(b) | ||
if err != nil { | ||
Fail(t, fmt.Sprintf("Failed to build http options, got error: %s", err)) | ||
} | ||
} | ||
Comment on lines
+184
to
+189
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If only a subset of options are provided, it should only assert that. Example: func handler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("hello"))
}
func TestHttp(t *testing.T) {
buf := bytes.NewBufferString("hello")
assert.HTTP(t, handler, http.MethodGet, "/", nil, assert.WithExpectedBody(*buf))
}
In general, if the all those options are not optional, they should not be variadic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To preserve the variadic options, then the |
||
|
||
w := httptest.NewRecorder() | ||
req, err := http.NewRequest(method, url, b.body) | ||
if b.err == nil && err != nil { | ||
Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) | ||
} else if b.err != nil { | ||
return err == b.err | ||
} | ||
|
||
req.Header = b.requestHeader | ||
req.URL.RawQuery = values.Encode() | ||
handler(w, req) | ||
if b.code != nil && w.Code != *b.code { | ||
Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), w.Code)) | ||
return false | ||
} | ||
|
||
if b.responseHeader != nil && !reflect.DeepEqual(w.HeaderMap, b.responseHeader) { | ||
Fail(t, fmt.Sprintf("Expected HTTP header to be equal for %q but received %v", url+"?"+values.Encode(), w.HeaderMap)) | ||
return false | ||
} | ||
|
||
contains := strings.Contains(w.Body.String(), b.expectedBody.String()) | ||
if !contains { | ||
Fail(t, fmt.Sprintf("Expected HTTP body to be equal for %q but received %s", url+"?"+values.Encode(), w.Body.String())) | ||
} | ||
|
||
return contains | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package assert | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
"io" | ||
http "net/http" | ||
) | ||
|
||
type builder struct { | ||
code *int | ||
body io.ReadCloser | ||
expectedBody bytes.Buffer | ||
requestHeader http.Header | ||
responseHeader http.Header | ||
err error | ||
} | ||
|
||
type HttpOption func(*builder) error | ||
|
||
func WithCode(code int) HttpOption { | ||
return func(b *builder) error { | ||
if code < 100 || code > 511 { | ||
return errors.New("Given HTTP code is outside range of possible values assignement") | ||
} | ||
|
||
b.code = &code | ||
return nil | ||
} | ||
} | ||
|
||
func WithErr(err error) HttpOption { | ||
return func(b *builder) error { | ||
b.err = err | ||
return nil | ||
} | ||
} | ||
|
||
func WithBody(body io.ReadCloser) HttpOption { | ||
return func(b *builder) error { | ||
b.body = body | ||
return nil | ||
} | ||
} | ||
|
||
func WithExpectedBody(expectedBody bytes.Buffer) HttpOption { | ||
return func(b *builder) error { | ||
b.expectedBody = expectedBody | ||
return nil | ||
} | ||
} | ||
|
||
func WithRequestHeader(requestHeader http.Header) HttpOption { | ||
return func(b *builder) error { | ||
b.requestHeader = requestHeader | ||
return nil | ||
} | ||
} | ||
|
||
func WithResponseHeader(responseHeader http.Header) HttpOption { | ||
return func(b *builder) error { | ||
b.responseHeader = responseHeader | ||
return nil | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the
options
is optional, should the builder have some defaults?Consider this:
Fails with:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point I have added the default code for builder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have made a change, based on what you said in next review step.
There are no defaults as the option would override something that is default for the builder. You mentioned that you expected that the
status.code
is not tested as You did not ask for it.As the options should be optional, I made a change when you select no option, there is nothing to be tested so the test fails. It is possible to to remove this check, however it is incorrectly tested
handler
as there is notassertion
.