-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: net/http/httptest: add support for http.ResponseController to ResponseRecorder #60229
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
Comments
ResponseRecorder type, which allows manipulating per-request timeouts. This is especially useful for programs managing long-running HTTP connections such as Mercure. However, testing HTTP handlers leveraging per-request timeouts is currently cumbersome (even if doable) because "net/http/httptest".ResponseRecorder isn't compatible yet with "http".ResponseController. This patch makes ResponseRecorder compatible with "http".ResponseController. All new methods are part of the contract that response types must honor to be usable with "http".ResponseController. NewRecorderWithDeadlineAwareRequest() is necessary to test read deadlines, as calling rw.SetReadDeadline() must change the deadline on the request body. Fixes golang#60229.
ResponseRecorder golang#54136 (implemented in Go 1.20) added the "http".ResponseController type, which allows manipulating per-request timeouts. This is especially useful for programs managing long-running HTTP connections such as Mercure. However, testing HTTP handlers leveraging per-request timeouts is currently cumbersome (even if doable) because "net/http/httptest".ResponseRecorder isn't compatible yet with "http".ResponseController. This patch makes ResponseRecorder compatible with "http".ResponseController. All new methods are part of the contract that response types must honor to be usable with "http".ResponseController. NewRecorderWithDeadlineAwareRequest() is necessary to test read deadlines, as calling rw.SetReadDeadline() must change the deadline on the request body. Fixes golang#60229. # Veuillez saisir le message de validation pour vos modifications. Les lignes # commençant par '#' seront conservées ; vous pouvez les supprimer vous-même # si vous le souhaitez. Un message vide abandonne la validation. # # Date : Mon May 15 17:59:56 2023 +0200 # # Sur la branche httptest_recorder_responsecontroller # Modifications qui seront validées : # modifié : net/http/httptest/example_test.go # modifié : net/http/httptest/recorder.go # modifié : net/http/httptest/recorder_test.go # modifié : net/http/server.go #
ResponseRecorder CL golang#54136 (implemented in Go 1.20) added the "http".ResponseController type, which allows manipulating per-request timeouts. This is especially useful for programs managing long-running HTTP connections such as Mercure. However, testing HTTP handlers leveraging per-request timeouts is currently cumbersome (even if doable) because "net/http/httptest".ResponseRecorder isn't compatible yet with "http".ResponseController. This patch makes ResponseRecorder compatible with "http".ResponseController. All new methods are part of the contract that response types must honor to be usable with "http".ResponseController. NewRecorderWithDeadlineAwareRequest() is necessary to test read deadlines, as calling rw.SetReadDeadline() must change the deadline on the request body. Fixes golang#60229.
…rder CL golang#54136 (implemented in Go 1.20) added the "http".ResponseController type, which allows manipulating per-request timeouts. This is especially useful for programs managing long-running HTTP connections such as Mercure. However, testing HTTP handlers leveraging per-request timeouts is currently cumbersome (even if doable) because "net/http/httptest".ResponseRecorder isn't compatible yet with "http".ResponseController. This patch makes ResponseRecorder compatible with "http".ResponseController. All new methods are part of the contract that response types must honor to be usable with "http".ResponseController. NewRecorderWithDeadlineAwareRequest() is necessary to test read deadlines, as calling rw.SetReadDeadline() must change the deadline on the request body. Fixes golang#60229.
Change https://go.dev/cl/495295 mentions this issue: |
I don't think It can't apply a real read deadline, since it has no good way to interrupt reads from the request body. In CL 495295, setting a read deadline causes Setting a write deadline can make write calls after the deadline has passed fail. Since Making reads and writes fail in this fashion seems out of scope for This also seems like an encouragement to write flaky tests. For example, in the example:
This may or may not write the response string to the recorder. If three seconds pass between the call to If you do want to write tests that rely on a record
|
Thanks for the quick and detailed feedback @neild. My main goal was to be able to easily assert that a deadline has been set (or changed) by the handler under test. I thought it was nice to have the full contract needed by It's definitely doable to implement a custom type similar to what is in this PR (it's already what we do for Mercure), but the developer experience is usually better when it's not necessary to write custom code to test native features. Do you think that there is value in providing the methods to set deadlines but not enforce them (to prevent flaky tests), or should I close this proposal and the related CL? |
Recording deadlines and not enforcing them would fit within So I'd be fine with adding record-only deadline methods. |
I updated the proposal and the related patch accordingly. |
As deadlines can be updated during the HTTP handler execution, would it be interesting to record all calls to The API would then be:
|
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
(Sorry for losing track of this.)
I think that this suggestion has moved me in the direction of thinking that we should not add any support for Recording deadlines has the fundamental problem that we don't know when the deadline was set. For example, whether we record a single
And the (probably) incorrect handler:
This gets worse if we have multiple deadlines applied across the course of the handler. I don't see how you can write a good test that asserts something like "the handler set deadlines of 1s, 10s, and 10s" without reference to what portions of the response those deadlines applied to. As I mentioned in #60229 (comment), if you really do want to do that style of recording, it isn't difficult to compose |
once the fix for golang/go#60229 makes it to the go version, this commit can be dropped
Based on the most recent reply, it sounds like we should not do this? |
This proposal has been added to the active column of the proposals project |
Based on the discussion above, this proposal seems like a likely decline. |
No change in consensus, so declined. |
Proposal #54136 (implemented in CL 436890 which is part of Go 1.20) added the
"http".ResponseController
type, which allows manipulating per-request timeouts. This is especially useful for programs managing long-running HTTP connections such as Mercure.However, testing HTTP handlers leveraging per-request timeouts is currently cumbersome (even if doable) because
"net/http/httptest".ResponseRecorder
isn't compatible yet with"http".ResponseController
.To make it fully compatible with response controllers and improve the testing experience, I propose the following additions to its public API:
All new methods are part of the contract that response types must honor to be usable with
"HTTP".ResponseController
.As discussed below, deadlines are recorded but not enforced to prevent flaky tests.
Proposal implementation: #60231
The text was updated successfully, but these errors were encountered: