diff --git a/README.md b/README.md index 8b49b45..ecebc9e 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,10 @@ import ( ) func TestSomething(t *testing.T) { - // Setup default test server and handler to log requests and return expected responses - // You may also create your own test server, handler, and mock to manage this + // Setup default test server and handler to log requests and return expected responses. + // You may also create your own test server, handler, and mock to manage this. ts := httpmock.NewServer() defer ts.Close() - // Set as recoverable to log panics rather than propagate out from the server - // goroutine to the parent process - ts.Recoverable() // Configure request mocks expectBearerToken := func(received *http.Request) (output string, differences int) { @@ -232,13 +229,12 @@ Mock.On(http.MethodGet, "/some/path", nil).RespondOK([]byte(`{"id": "1234"}`)).H ### `httpmock.Server` -#### Recoverable, IsRecoverable +#### NotRecoverable, IsRecoverable `httpmock.Server` is a glorified version of `httptest.Server` with a default handler. With both server types, the -server runs as a goroutine. One can use `Recoverable()` to indicate that an unmatched request should not cause the -server to panic outside of the server goroutine and into the main process. - -If writing a custom handler, the handler should react to a panic based on the server's `IsRecoverable()` response. +server runs as a goroutine. The default behavior is to log the panic details and recover from it. However, an +implementation can set `NotRecoverable()` to indicate to the handler that an unmatched request should cause the server +to panic outside of the server goroutine and into the main process. ## Installation diff --git a/server.go b/server.go index eeb4e2b..1b1a65a 100644 --- a/server.go +++ b/server.go @@ -15,9 +15,9 @@ type Server struct { Mock *Mock // Whether or not panics should be caught in the server goroutine or - // allowed to propagate to the parent process. If true, the panic will be + // allowed to propagate to the parent process. If false, the panic will be // printed and a 404 will be returned to the client. - recoverable bool + ignorePanic bool } // makeHandler creates a standard [http.HandlerFunc] that may be used by a @@ -62,21 +62,20 @@ func NewTLSServer() *Server { return s } -// Recoverable sets a [Server] as recoverable, so that panics are caught and -// printed to stdout, with a final 404 returned to the client. +// NotRecoverable sets a [Server] as not recoverable, so that panics are allowed +// to propagate to the main process. With the default handler, panics are caught +// and printed to stdout, with a final 404 returned to the client. // // 404 was chosen rather than 500 due to panics almost always occurring when a -// matching [Request] cannot be found. However, custom handlers can choose to -// implement their recovery mechanism however they would like, using the -// [Server.IsRecoverable] method to access this value. -func (s *Server) Recoverable() *Server { - s.recoverable = true +// matching [Request] cannot be found. +func (s *Server) NotRecoverable() *Server { + s.ignorePanic = true return s } // IsRecoverable returns whether or not the [Server] is considered recoverable. func (s *Server) IsRecoverable() bool { - return s.recoverable + return !s.ignorePanic } // On is a convenience method to invoke the [Mock.On] method. diff --git a/server_test.go b/server_test.go index 9bc9e2d..dd87cd3 100644 --- a/server_test.go +++ b/server_test.go @@ -41,9 +41,21 @@ func Test_NewTLSServer(t *testing.T) { } } -func TestServer_handler_NoMatch(t *testing.T) { +func TestServer_NotRecoverable(t *testing.T) { // Setup - s := NewServer().Recoverable() + s := NewServer() + defer s.Close() + + // Test + s.NotRecoverable() + + // Assert + assert.True(t, s.ignorePanic) +} + +func TestServer_defaultHandler_NoMatch(t *testing.T) { + // Setup + s := NewServer() defer s.Close() s.On(http.MethodGet, "/foo/1234", nil).RespondOK([]byte(testBody)) @@ -60,9 +72,9 @@ func TestServer_handler_NoMatch(t *testing.T) { s.Mock.AssertNotRequested(t, http.MethodDelete, fmt.Sprintf("%s/foo/1234", s.URL), nil) } -func TestServer_handler_AssertRequested(t *testing.T) { +func TestServer_defaultHandler_AssertRequested(t *testing.T) { // Setup - s := NewServer().Recoverable() + s := NewServer() defer s.Close() s.On(http.MethodGet, "/foo/1234", nil).RespondOK([]byte(testBody)) @@ -86,9 +98,9 @@ func TestServer_handler_AssertRequested(t *testing.T) { s.Mock.AssertRequested(t, http.MethodGet, "/foo/1234", nil) } -func TestServer_handler_AssertNotRequested(t *testing.T) { +func TestServer_defaultHandler_AssertNotRequested(t *testing.T) { // Setup - s := NewServer().Recoverable() + s := NewServer() defer s.Close() s.On(http.MethodGet, "/foo/1234", nil).RespondOK([]byte(testBody)) @@ -96,9 +108,9 @@ func TestServer_handler_AssertNotRequested(t *testing.T) { s.Mock.AssertNotRequested(t, http.MethodDelete, fmt.Sprintf("%s/foo/1234", s.URL), nil) } -func TestServer_handler_AssertExpectations(t *testing.T) { +func TestServer_defaultHandler_AssertExpectations(t *testing.T) { // Setup - s := NewServer().Recoverable() + s := NewServer() defer s.Close() s.On(http.MethodGet, "/foo/1234", nil).Respond(http.StatusNotFound, nil).Twice() s.On(http.MethodPut, "/foo/1234", []byte(testBody)).RespondNoContent() @@ -163,9 +175,9 @@ func TestServer_handler_AssertExpectations(t *testing.T) { s.Mock.AssertExpectations(t) } -func TestServer_handler_AssertNumberOfRequests(t *testing.T) { +func TestServer_defaultHandler_AssertNumberOfRequests(t *testing.T) { // Setup - s := NewServer().Recoverable() + s := NewServer() defer s.Close() s.On(http.MethodGet, "/foo/1234", nil).Respond(http.StatusNotFound, nil).Twice() s.On(http.MethodPut, "/foo/1234", []byte(testBody)).RespondNoContent() @@ -246,13 +258,10 @@ func TestServer_handler_AssertNumberOfRequests(t *testing.T) { // // Let's keep it as a real test to ensure it actually works! func TestSomething(t *testing.T) { - // Setup default test server and handler to log requests and return expected responses - // You may also create your own test server, handler, and mock to manage this + // Setup default test server and handler to log requests and return expected responses. + // You may also create your own test server, handler, and mock to manage this. ts := NewServer() defer ts.Close() - // Set as recoverable to log panics rather than propagate out from the server - // goroutine to the parent process - ts.Recoverable() // Configure request mocks expectBearerToken := func(received *http.Request) (output string, differences int) {