Skip to content

Commit ca033c5

Browse files
committed
MockRouter/MockContext fix a couple of bugs and simplify usage
1 parent a724f69 commit ca033c5

8 files changed

Lines changed: 121 additions & 37 deletions

File tree

jooby/src/main/java/io/jooby/Context.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -604,7 +604,7 @@ public interface Context extends Registry {
604604
* @param <T> Conversion type.
605605
* @return Instance of conversion type.
606606
*/
607-
@Nonnull <T> T body(@Nonnull Class type);
607+
@Nonnull <T> T body(@Nonnull Class<T> type);
608608

609609
/**
610610
* Convert the HTTP body to the given type.
@@ -614,7 +614,7 @@ public interface Context extends Registry {
614614
* @param <T> Conversion type.
615615
* @return Instance of conversion type.
616616
*/
617-
@Nonnull <T> T body(@Nonnull Class type, @Nonnull MediaType contentType);
617+
@Nonnull <T> T body(@Nonnull Class<T> type, @Nonnull MediaType contentType);
618618

619619
/* **********************************************************************************************
620620
* Body MessageDecoder

jooby/src/main/java/io/jooby/DefaultContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,11 @@ public interface DefaultContext extends Context {
319319
}
320320
}
321321

322-
@Override default @Nonnull <T> T body(@Nonnull Class type) {
322+
@Override default @Nonnull <T> T body(@Nonnull Class<T> type) {
323323
return body(type, getRequestType(MediaType.text));
324324
}
325325

326-
@Override default @Nonnull <T> T body(@Nonnull Class type, @Nonnull MediaType contentType) {
326+
@Override default @Nonnull <T> T body(@Nonnull Class<T> type, @Nonnull MediaType contentType) {
327327
try {
328328
return decoder(contentType).decode(this, type);
329329
} catch (Exception x) {

jooby/src/main/java/io/jooby/ForwardingContext.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,11 @@ public ForwardingContext(@Nonnull Context context) {
273273
return context.body(type, contentType);
274274
}
275275

276-
@Nonnull @Override public <T> T body(@Nonnull Class type) {
276+
@Nonnull @Override public <T> T body(@Nonnull Class<T> type) {
277277
return context.body(type);
278278
}
279279

280-
@Nonnull @Override public <T> T body(@Nonnull Class type, @Nonnull MediaType contentType) {
280+
@Nonnull @Override public <T> T body(@Nonnull Class<T> type, @Nonnull MediaType contentType) {
281281
return context.body(type, contentType);
282282
}
283283

modules/jooby-apt/src/test/java/tests/HandlerCompilerTest.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,14 @@ public void multipleParameters() throws Exception {
205205
@Test
206206
public void fileParam() throws Exception {
207207
FileUpload file = mock(FileUpload.class);
208-
Multipart multipart = Multipart.create();
209-
multipart.put("file", file);
208+
when(file.name()).thenReturn("file");
210209
new MvcHandlerCompilerRunner(new Provisioning())
211210
.compile("/p/fileParam", handler -> {
212-
assertEquals(file.toString(), handler.apply(new MockContext().setMultipart(multipart)));
211+
assertEquals(file.toString(), handler.apply(new MockContext().setFiles(Arrays.asList(file))));
213212
})
214213
.compile("/p/fileParams", handler -> {
215214
assertEquals(Arrays.asList(file).toString(),
216-
handler.apply(new MockContext().setMultipart(multipart)));
215+
handler.apply(new MockContext().setFiles(Arrays.asList(file))));
217216
})
218217
;
219218
}
@@ -246,10 +245,9 @@ public void specialParam() throws Exception {
246245
Path path = mock(Path.class);
247246
FileUpload file = mock(FileUpload.class);
248247
when(file.path()).thenReturn(path);
249-
Multipart multipart = Multipart.create();
250-
multipart.put("file", file);
248+
when(file.name()).thenReturn("file");
251249
assertEquals(path.toString(),
252-
handler.apply(new MockContext().setMultipart(multipart)));
250+
handler.apply(new MockContext().setFiles(Arrays.asList(file))));
253251
})
254252
;
255253
}

modules/jooby-test/src/main/java/io/jooby/MockContext.java

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
import java.nio.channels.ReadableByteChannel;
1919
import java.nio.charset.Charset;
2020
import java.nio.charset.StandardCharsets;
21-
import java.time.Instant;
21+
import java.nio.file.Path;
2222
import java.util.ArrayList;
2323
import java.util.Collection;
24-
import java.util.Date;
2524
import java.util.HashMap;
2625
import java.util.LinkedHashMap;
26+
import java.util.List;
2727
import java.util.Map;
2828
import 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
}

modules/jooby-test/src/test/java/io/jooby/MvcController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import io.jooby.annotations.Dispatch;
1919
import io.jooby.annotations.GET;
20+
import io.jooby.annotations.POST;
2021
import io.jooby.annotations.Path;
2122

2223
@Path("/mvc")
@@ -32,4 +33,9 @@ public String getIt(Context ctx) {
3233
public String single() {
3334
return Thread.currentThread().getName();
3435
}
36+
37+
@POST
38+
public PojoBody post(PojoBody body) {
39+
return body;
40+
}
3541
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package io.jooby;
2+
3+
public class PojoBody {
4+
}

modules/jooby-test/src/test/java/io/jooby/UnitTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public void unitTests() {
2424

2525
app.post("/", ctx -> ctx.body().value());
2626

27+
app.post("/pojo", ctx -> ctx.body(PojoBody.class));
28+
2729
MockRouter router = new MockRouter(app);
2830

2931
assertEquals("OK", router.get("/").value());
@@ -54,6 +56,15 @@ public void unitTests() {
5456
router.post("/", new MockContext().setBody(body), result -> {
5557
assertEquals(body, result.value());
5658
});
59+
60+
PojoBody pojo = new PojoBody();
61+
router.post("/pojo", new MockContext().setBody(pojo), result -> {
62+
assertEquals(pojo, result.value());
63+
});
64+
65+
router.get("/x/notfound", new MockContext().setBody(pojo), result -> {
66+
assertEquals(StatusCode.NOT_FOUND, result.getStatusCode());
67+
});
5768
}
5869

5970
@Test
@@ -119,6 +130,9 @@ public void rx() {
119130
public void mvcApp() {
120131
MockRouter router = new MockRouter(new MvcApp());
121132
assertEquals("/mvc", router.get("/mvc").value());
133+
134+
PojoBody body = new PojoBody();
135+
assertEquals(body, router.post("/mvc", new MockContext().setBody(body)).value());
122136
}
123137

124138
}

0 commit comments

Comments
 (0)