1818import java .nio .channels .ReadableByteChannel ;
1919import java .nio .charset .Charset ;
2020import java .nio .charset .StandardCharsets ;
21- import java .time . Instant ;
21+ import java .nio . file . Path ;
2222import java .util .ArrayList ;
2323import java .util .Collection ;
24- import java .util .Date ;
2524import java .util .HashMap ;
2625import java .util .LinkedHashMap ;
26+ import java .util .List ;
2727import java .util .Map ;
2828import java .util .concurrent .Executor ;
29+ import java .util .stream .Collectors ;
2930
3031/**
3132 * Unit test friendly context implementation. Allows to set context properties.
@@ -50,7 +51,9 @@ public class MockContext implements DefaultContext {
5051
5152 private Body body ;
5253
53- private Map <String , MessageDecoder > parsers = new HashMap <>();
54+ private Object bodyObject ;
55+
56+ private Map <String , MessageDecoder > decoders = new HashMap <>();
5457
5558 private Map <String , Object > responseHeaders = new HashMap <>();
5659
@@ -66,6 +69,7 @@ public class MockContext implements DefaultContext {
6669
6770 private Router router ;
6871
72+ private List <FileUpload > files = new ArrayList <>();
6973
7074 @ Nonnull @ Override public String getMethod () {
7175 return method ;
@@ -224,6 +228,24 @@ public MockContext setPathString(@Nonnull String pathString) {
224228 return multipart ;
225229 }
226230
231+ @ Nonnull @ Override public List <FileUpload > files () {
232+ return files ;
233+ }
234+
235+ public MockContext setFiles (@ Nonnull List <FileUpload > files ) {
236+ this .files = files ;
237+ return this ;
238+ }
239+
240+ @ Nonnull @ Override public List <FileUpload > files (@ Nonnull String name ) {
241+ return files .stream ().filter (it -> it .name ().equals (name )).collect (Collectors .toList ());
242+ }
243+
244+ @ Nonnull @ Override public FileUpload file (@ Nonnull String name ) {
245+ return files .stream ().filter (it -> it .name ().equals (name )).findFirst ()
246+ .orElseThrow (() -> new TypeMismatchException (name , FileUpload .class ));
247+ }
248+
227249 /**
228250 * Set multipart.
229251 *
@@ -242,14 +264,52 @@ public MockContext setPathString(@Nonnull String pathString) {
242264 return body ;
243265 }
244266
267+ @ Nonnull @ Override public <T > T body (@ Nonnull Reified <T > type ) {
268+ if (bodyObject == null ) {
269+ throw new IllegalStateException ("No body was set, use setBody() to set one." );
270+ }
271+ if (!type .getRawType ().isInstance (bodyObject )) {
272+ throw new TypeMismatchException ("body" , FileUpload .class );
273+ }
274+ return body (type , MediaType .text );
275+ }
276+
277+ @ Nonnull @ Override public <T > T body (@ Nonnull Reified <T > type , @ Nonnull MediaType contentType ) {
278+ if (bodyObject == null ) {
279+ throw new IllegalStateException ("No body was set, use setBody() to set one." );
280+ }
281+ if (!type .getRawType ().isInstance (bodyObject )) {
282+ throw new TypeMismatchException ("body" , type .getType ());
283+ }
284+ return (T ) type .getRawType ().cast (bodyObject );
285+ }
286+
287+ @ Nonnull @ Override public <T > T body (@ Nonnull Class <T > type ) {
288+ return body (type , MediaType .text );
289+ }
290+
291+ @ Nonnull @ Override public <T > T body (@ Nonnull Class <T > type , @ Nonnull MediaType contentType ) {
292+ if (bodyObject == null ) {
293+ throw new IllegalStateException ("No body was set, use setBody() to set one." );
294+ }
295+ if (!type .isInstance (bodyObject )) {
296+ throw new TypeMismatchException ("body" , type );
297+ }
298+ return type .cast (bodyObject );
299+ }
300+
245301 /**
246302 * Set request body.
247303 *
248304 * @param body Request body.
249305 * @return This context.
250306 */
251- @ Nonnull public MockContext setBody (@ Nonnull Body body ) {
252- this .body = body ;
307+ @ Nonnull public MockContext setBody (@ Nonnull Object body ) {
308+ if (body instanceof Body ) {
309+ this .body = (Body ) body ;
310+ } else {
311+ this .bodyObject = body ;
312+ }
253313 return this ;
254314 }
255315
@@ -276,7 +336,7 @@ public MockContext setPathString(@Nonnull String pathString) {
276336 }
277337
278338 @ Nonnull @ Override public MessageDecoder decoder (@ Nonnull MediaType contentType ) {
279- return parsers .getOrDefault (contentType , MessageDecoder .UNSUPPORTED_MEDIA_TYPE );
339+ return decoders .getOrDefault (contentType , MessageDecoder .UNSUPPORTED_MEDIA_TYPE );
280340 }
281341
282342 @ Override public boolean isInIoThread () {
@@ -303,29 +363,11 @@ public MockContext dispatch(@Nonnull Executor executor, @Nonnull Runnable action
303363 return attributes ;
304364 }
305365
306- @ Nonnull @ Override
307- public MockContext setResponseHeader (@ Nonnull String name , @ Nonnull Date value ) {
308- DefaultContext .super .setResponseHeader (name , value );
309- return this ;
310- }
311-
312366 @ Nonnull @ Override public MockContext removeResponseHeader (@ Nonnull String name ) {
313367 responseHeaders .remove (name );
314368 return this ;
315369 }
316370
317- @ Nonnull @ Override
318- public MockContext setResponseHeader (@ Nonnull String name , @ Nonnull Instant value ) {
319- DefaultContext .super .setResponseHeader (name , value );
320- return this ;
321- }
322-
323- @ Nonnull @ Override
324- public MockContext setResponseHeader (@ Nonnull String name , @ Nonnull Object value ) {
325- DefaultContext .super .setResponseHeader (name , value );
326- return this ;
327- }
328-
329371 @ Nonnull @ Override
330372 public MockContext setResponseHeader (@ Nonnull String name , @ Nonnull String value ) {
331373 responseHeaders .put (name , value );
@@ -433,6 +475,16 @@ public MockContext setResponseType(@Nonnull MediaType contentType, @Nullable Cha
433475 return this ;
434476 }
435477
478+ @ Nonnull @ Override public Context send (@ Nonnull AttachedFile file ) {
479+ this .response .setResult (file );
480+ return this ;
481+ }
482+
483+ @ Nonnull @ Override public Context send (@ Nonnull Path file ) {
484+ this .response .setResult (file );
485+ return this ;
486+ }
487+
436488 @ Nonnull @ Override public MockContext send (@ Nonnull ReadableByteChannel channel ) {
437489 this .response .setResult (channel );
438490 return this ;
@@ -451,6 +503,11 @@ public MockContext setResponseType(@Nonnull MediaType contentType, @Nullable Cha
451503 }
452504
453505 @ Nonnull @ Override public MockContext sendError (@ Nonnull Throwable cause ) {
506+ return sendError (cause , router .errorCode (cause ));
507+ }
508+
509+ @ Nonnull @ Override
510+ public MockContext sendError (@ Nonnull Throwable cause , @ Nonnull StatusCode statusCode ) {
454511 this .response .setResult (cause )
455512 .setStatusCode (router .errorCode (cause ));
456513 return this ;
@@ -476,6 +533,11 @@ public MockContext setResponseType(@Nonnull MediaType contentType, @Nullable Cha
476533 return response .getContentType ();
477534 }
478535
536+ @ Nonnull @ Override public MockContext setResponseCode (@ Nonnull StatusCode statusCode ) {
537+ response .setStatusCode (statusCode );
538+ return this ;
539+ }
540+
479541 @ Override public boolean isResponseStarted () {
480542 return response .value () != null ;
481543 }
0 commit comments