1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ //nolint:err113
1516package errors
1617
1718import (
@@ -31,120 +32,175 @@ type customError struct {
3132}
3233
3334func TestServeError (t * testing.T ) {
34- // method not allowed wins
35- // err abides by the Error interface
36- err := MethodNotAllowed ("GET" , []string {"POST" , "PUT" })
37- recorder := httptest .NewRecorder ()
38- ServeError (recorder , nil , err )
39- assert .Equal (t , http .StatusMethodNotAllowed , recorder .Code )
40- assert .Equal (t , "POST,PUT" , recorder .Header ().Get ("Allow" ))
41- // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
42- assert .Equal (t , `{"code":405,"message":"method GET is not allowed, but [POST,PUT] are"}` , recorder .Body .String ())
43-
44- // renders status code from error when present
45- err = NotFound ("" )
46- recorder = httptest .NewRecorder ()
47- ServeError (recorder , nil , err )
48- assert .Equal (t , http .StatusNotFound , recorder .Code )
49- // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
50- assert .Equal (t , `{"code":404,"message":"Not found"}` , recorder .Body .String ())
51-
52- // renders mapped status code from error when present
53- err = InvalidTypeName ("someType" )
54- recorder = httptest .NewRecorder ()
55- ServeError (recorder , nil , err )
56- assert .Equal (t , http .StatusUnprocessableEntity , recorder .Code )
57- // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
58- assert .Equal (t , `{"code":601,"message":"someType is an invalid type name"}` , recorder .Body .String ())
59-
60- // same, but override DefaultHTTPCode
61- func () {
62- oldDefaultHTTPCode := DefaultHTTPCode
63- defer func () { DefaultHTTPCode = oldDefaultHTTPCode }()
64- DefaultHTTPCode = http .StatusBadRequest
65-
66- err = InvalidTypeName ("someType" )
67- recorder = httptest .NewRecorder ()
35+ t .Run ("method not allowed wins" , func (t * testing.T ) {
36+ // err abides by the Error interface
37+ err := MethodNotAllowed ("GET" , []string {"POST" , "PUT" })
38+ require .Error (t , err )
39+
40+ recorder := httptest .NewRecorder ()
41+ ServeError (recorder , nil , err )
42+ assert .Equal (t , http .StatusMethodNotAllowed , recorder .Code )
43+ assert .Equal (t , "POST,PUT" , recorder .Header ().Get ("Allow" ))
44+ // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
45+ assert .JSONEq (t ,
46+ `{"code":405,"message":"method GET is not allowed, but [POST,PUT] are"}` ,
47+ recorder .Body .String (),
48+ )
49+ })
50+
51+ t .Run ("renders status code from error" , func (t * testing.T ) {
52+ err := NotFound ("" )
53+ require .Error (t , err )
54+
55+ recorder := httptest .NewRecorder ()
56+ ServeError (recorder , nil , err )
57+ assert .Equal (t , http .StatusNotFound , recorder .Code )
58+ // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
59+ assert .JSONEq (t ,
60+ `{"code":404,"message":"Not found"}` ,
61+ recorder .Body .String (),
62+ )
63+ })
64+
65+ t .Run ("renders mapped status code from error" , func (t * testing.T ) {
66+ // renders mapped status code from error when present
67+ err := InvalidTypeName ("someType" )
68+ require .Error (t , err )
69+
70+ recorder := httptest .NewRecorder ()
6871 ServeError (recorder , nil , err )
69- assert .Equal (t , http .StatusBadRequest , recorder .Code )
72+ assert .Equal (t , http .StatusUnprocessableEntity , recorder .Code )
7073 // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
71- assert .Equal (t , `{"code":601,"message":"someType is an invalid type name"}` , recorder .Body .String ())
72- }()
73-
74- // defaults to internal server error
75- simpleErr := errors .New ("some error" )
76- recorder = httptest .NewRecorder ()
77- ServeError (recorder , nil , simpleErr )
78- assert .Equal (t , http .StatusInternalServerError , recorder .Code )
79- // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
80- assert .Equal (t , `{"code":500,"message":"some error"}` , recorder .Body .String ())
81-
82- // composite errors
83-
84- // unrecognized: return internal error with first error only - the second error is ignored
85- compositeErr := & CompositeError {
86- Errors : []error {
87- errors .New ("firstError" ),
88- errors .New ("anotherError" ),
89- },
90- }
91- recorder = httptest .NewRecorder ()
92- ServeError (recorder , nil , compositeErr )
93- assert .Equal (t , http .StatusInternalServerError , recorder .Code )
94- assert .Equal (t , `{"code":500,"message":"firstError"}` , recorder .Body .String ())
95-
96- // recognized: return internal error with first error only - the second error is ignored
97- compositeErr = & CompositeError {
98- Errors : []error {
99- New (600 , "myApiError" ),
100- New (601 , "myOtherApiError" ),
101- },
102- }
103- recorder = httptest .NewRecorder ()
104- ServeError (recorder , nil , compositeErr )
105- assert .Equal (t , CompositeErrorCode , recorder .Code )
106- assert .Equal (t , `{"code":600,"message":"myApiError"}` , recorder .Body .String ())
107-
108- // recognized API Error, flattened
109- compositeErr = & CompositeError {
110- Errors : []error {
111- & CompositeError {
74+ assert .JSONEq (t ,
75+ `{"code":601,"message":"someType is an invalid type name"}` ,
76+ recorder .Body .String (),
77+ )
78+ })
79+
80+ t .Run ("overrides DefaultHTTPCode" , func (t * testing.T ) {
81+ func () {
82+ oldDefaultHTTPCode := DefaultHTTPCode
83+ defer func () { DefaultHTTPCode = oldDefaultHTTPCode }()
84+ DefaultHTTPCode = http .StatusBadRequest
85+
86+ err := InvalidTypeName ("someType" )
87+ require .Error (t , err )
88+
89+ recorder := httptest .NewRecorder ()
90+ ServeError (recorder , nil , err )
91+ assert .Equal (t , http .StatusBadRequest , recorder .Code )
92+ // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
93+ assert .JSONEq (t ,
94+ `{"code":601,"message":"someType is an invalid type name"}` ,
95+ recorder .Body .String (),
96+ )
97+ }()
98+ })
99+
100+ t .Run ("defaults to internal server error" , func (t * testing.T ) {
101+ simpleErr := errors .New ("some error" )
102+ recorder := httptest .NewRecorder ()
103+ ServeError (recorder , nil , simpleErr )
104+ assert .Equal (t , http .StatusInternalServerError , recorder .Code )
105+ // assert.Equal(t, "application/json", recorder.Header().Get("content-type"))
106+ assert .JSONEq (t ,
107+ `{"code":500,"message":"some error"}` ,
108+ recorder .Body .String (),
109+ )
110+ })
111+
112+ t .Run ("with composite erors" , func (t * testing.T ) {
113+ t .Run ("unrecognized - return internal error with first error only - the second error is ignored" , func (t * testing.T ) {
114+ compositeErr := & CompositeError {
115+ Errors : []error {
116+ errors .New ("firstError" ),
117+ errors .New ("anotherError" ),
118+ },
119+ }
120+ recorder := httptest .NewRecorder ()
121+ ServeError (recorder , nil , compositeErr )
122+ assert .Equal (t , http .StatusInternalServerError , recorder .Code )
123+ assert .JSONEq (t ,
124+ `{"code":500,"message":"firstError"}` ,
125+ recorder .Body .String (),
126+ )
127+ })
128+
129+ t .Run ("recognized - return internal error with first error only - the second error is ignored" , func (t * testing.T ) {
130+ compositeErr := & CompositeError {
112131 Errors : []error {
113132 New (600 , "myApiError" ),
114133 New (601 , "myOtherApiError" ),
115134 },
116- },
117- },
118- }
119- recorder = httptest .NewRecorder ()
120- ServeError (recorder , nil , compositeErr )
121- assert .Equal (t , CompositeErrorCode , recorder .Code )
122- assert .Equal (t , `{"code":600,"message":"myApiError"}` , recorder .Body .String ())
123-
124- // check guard against empty CompositeError (e.g. nil Error interface)
125- compositeErr = & CompositeError {
126- Errors : []error {
127- & CompositeError {
128- Errors : []error {},
129- },
130- },
131- }
132- recorder = httptest .NewRecorder ()
133- ServeError (recorder , nil , compositeErr )
134- assert .Equal (t , http .StatusInternalServerError , recorder .Code )
135- assert .Equal (t , `{"code":500,"message":"Unknown error"}` , recorder .Body .String ())
136-
137- // check guard against nil type
138- recorder = httptest .NewRecorder ()
139- ServeError (recorder , nil , nil )
140- assert .Equal (t , http .StatusInternalServerError , recorder .Code )
141- assert .Equal (t , `{"code":500,"message":"Unknown error"}` , recorder .Body .String ())
142-
143- recorder = httptest .NewRecorder ()
144- var z * customError
145- ServeError (recorder , nil , z )
146- assert .Equal (t , http .StatusInternalServerError , recorder .Code )
147- assert .Equal (t , `{"code":500,"message":"Unknown error"}` , recorder .Body .String ())
135+ }
136+ recorder := httptest .NewRecorder ()
137+ ServeError (recorder , nil , compositeErr )
138+ assert .Equal (t , CompositeErrorCode , recorder .Code )
139+ assert .JSONEq (t ,
140+ `{"code":600,"message":"myApiError"}` ,
141+ recorder .Body .String (),
142+ )
143+ })
144+
145+ t .Run ("recognized API Error, flattened" , func (t * testing.T ) {
146+ compositeErr := & CompositeError {
147+ Errors : []error {
148+ & CompositeError {
149+ Errors : []error {
150+ New (600 , "myApiError" ),
151+ New (601 , "myOtherApiError" ),
152+ },
153+ },
154+ },
155+ }
156+ recorder := httptest .NewRecorder ()
157+ ServeError (recorder , nil , compositeErr )
158+ assert .Equal (t , CompositeErrorCode , recorder .Code )
159+ assert .JSONEq (t ,
160+ `{"code":600,"message":"myApiError"}` ,
161+ recorder .Body .String (),
162+ )
163+ })
164+
165+ // (e.g. nil Error interface)
166+ t .Run ("check guard against empty CompositeError" , func (t * testing.T ) {
167+ compositeErr := & CompositeError {
168+ Errors : []error {
169+ & CompositeError {
170+ Errors : []error {},
171+ },
172+ },
173+ }
174+ recorder := httptest .NewRecorder ()
175+ ServeError (recorder , nil , compositeErr )
176+ assert .Equal (t , http .StatusInternalServerError , recorder .Code )
177+ assert .JSONEq (t ,
178+ `{"code":500,"message":"Unknown error"}` ,
179+ recorder .Body .String (),
180+ )
181+ })
182+
183+ t .Run ("check guard against nil type" , func (t * testing.T ) {
184+ recorder := httptest .NewRecorder ()
185+ ServeError (recorder , nil , nil )
186+ assert .Equal (t , http .StatusInternalServerError , recorder .Code )
187+ assert .JSONEq (t ,
188+ `{"code":500,"message":"Unknown error"}` ,
189+ recorder .Body .String (),
190+ )
191+ })
192+
193+ t .Run ("check guard against nil value" , func (t * testing.T ) {
194+ recorder := httptest .NewRecorder ()
195+ var z * customError
196+ ServeError (recorder , nil , z )
197+ assert .Equal (t , http .StatusInternalServerError , recorder .Code )
198+ assert .JSONEq (t ,
199+ `{"code":500,"message":"Unknown error"}` ,
200+ recorder .Body .String (),
201+ )
202+ })
203+ })
148204}
149205
150206func TestAPIErrors (t * testing.T ) {
0 commit comments