@@ -253,56 +253,76 @@ public <T, S extends Publisher<T>> ResponseSpec exchange(S publisher, Class<T> e
253253 return toResponseSpec (this .headerSpec .exchange (publisher , elementClass ));
254254 }
255255
256- private DefaultResponseSpec toResponseSpec (Mono <ClientResponse > responseMono ) {
257- ClientResponse response = responseMono .block (getTimeout ());
258- ClientHttpRequest request = webTestClientConnector .claimRequest (this .requestId );
259- ExchangeResult <Flux <DataBuffer >> result = ExchangeResult .create (request , response );
260- return new DefaultResponseSpec (result , response );
256+ private DefaultResponseSpec toResponseSpec (Mono <ClientResponse > mono ) {
257+ ClientResponse response = mono .block (getTimeout ());
258+ ClientHttpRequest httpRequest = webTestClientConnector .claimRequest (this .requestId );
259+ return new DefaultResponseSpec (httpRequest , response );
261260 }
262261 }
263262
264- private abstract class ResponseSpecSupport {
265-
266- private final ExchangeResult <Flux <DataBuffer >> exchangeResult ;
263+ /**
264+ * ExchangeResult that contains the live {@link ClientResponse}.
265+ */
266+ private class UndecodedExchangeResult extends ExchangeResult {
267267
268268 private final ClientResponse response ;
269269
270270
271- public ResponseSpecSupport ( ExchangeResult < Flux < DataBuffer >> result , ClientResponse response ) {
272- this . exchangeResult = result ;
271+ public UndecodedExchangeResult ( ClientHttpRequest httpRequest , ClientResponse response ) {
272+ super ( httpRequest , response ) ;
273273 this .response = response ;
274274 }
275275
276276
277- protected ExchangeResult <Flux <DataBuffer >> getExchangeResult () {
278- return this .exchangeResult ;
277+ public EntityExchangeResult <?> consumeSingle (ResolvableType elementType ) {
278+ Object body = this .response .body (toMono (elementType )).block (getTimeout ());
279+ return new EntityExchangeResult <>(this , body );
279280 }
280281
281- protected ClientResponse getResponse () {
282- return this .response ;
282+ public EntityExchangeResult <List <?>> consumeList (ResolvableType elementType , int count ) {
283+ Flux <?> flux = this .response .body (toFlux (elementType ));
284+ if (count >= 0 ) {
285+ flux = flux .take (count );
286+ }
287+ List <?> body = flux .collectList ().block (getTimeout ());
288+ return new EntityExchangeResult <>(this , body );
283289 }
284290
285- protected <T > ExchangeResult <T > createResultWithDecodedBody (T body ) {
286- return ExchangeResult .withDecodedBody (this .exchangeResult , body );
291+ public <T > FluxExchangeResult <T > decodeBody (ResolvableType elementType ) {
292+ Flux <T > body = this .response .body (toFlux (elementType ));
293+ return new FluxExchangeResult <>(this , body , elementType );
287294 }
288295
296+ @ SuppressWarnings ("unchecked" )
297+ public EntityExchangeResult <Map <?, ?>> consumeMap (ResolvableType keyType , ResolvableType valueType ) {
298+ ResolvableType mapType = ResolvableType .forClassWithGenerics (Map .class , keyType , valueType );
299+ return (EntityExchangeResult <Map <?, ?>>) consumeSingle (mapType );
300+ }
301+
302+ public EntityExchangeResult <Void > consumeEmpty () {
303+ DataBuffer buffer = this .response .body (toDataBuffers ()).blockFirst (getTimeout ());
304+ assertTrue ("Expected empty body" , buffer == null );
305+ return new EntityExchangeResult <>(this , null );
306+ }
289307 }
290308
291- private class DefaultResponseSpec extends ResponseSpecSupport implements ResponseSpec {
309+ private class DefaultResponseSpec implements ResponseSpec {
292310
311+ private final UndecodedExchangeResult exchangeResult ;
293312
294- public DefaultResponseSpec (ExchangeResult <Flux <DataBuffer >> exchangeResult , ClientResponse response ) {
295- super (exchangeResult , response );
313+
314+ public DefaultResponseSpec (ClientHttpRequest httpRequest , ClientResponse response ) {
315+ this .exchangeResult = new UndecodedExchangeResult (httpRequest , response );
296316 }
297317
298318 @ Override
299319 public StatusAssertions expectStatus () {
300- return new StatusAssertions (getExchangeResult () , this );
320+ return new StatusAssertions (this . exchangeResult , this );
301321 }
302322
303323 @ Override
304324 public HeaderAssertions expectHeader () {
305- return new HeaderAssertions (getExchangeResult () , this );
325+ return new HeaderAssertions (this . exchangeResult , this );
306326 }
307327
308328 @ Override
@@ -312,40 +332,43 @@ public TypeBodySpec expectBody(Class<?> elementType) {
312332
313333 @ Override
314334 public TypeBodySpec expectBody (ResolvableType elementType ) {
315- return new DefaultTypeBodySpec (this , elementType );
335+ return new DefaultTypeBodySpec (this . exchangeResult , elementType );
316336 }
317337
318338 @ Override
319339 public BodySpec expectBody () {
320- return new DefaultBodySpec (this );
340+ return new DefaultBodySpec (this . exchangeResult );
321341 }
322342
323343 @ Override
324- public ResponseSpec consumeWith (Consumer <ExchangeResult < Flux < DataBuffer >> > consumer ) {
325- consumer .accept (getExchangeResult () );
344+ public ResponseSpec consumeWith (Consumer <ExchangeResult > consumer ) {
345+ consumer .accept (this . exchangeResult );
326346 return this ;
327347 }
328348
329349 @ Override
330- public ExchangeResult < Flux < DataBuffer >> returnResult () {
331- return getExchangeResult () ;
350+ public ExchangeResult returnResult () {
351+ return this . exchangeResult ;
332352 }
333353 }
334354
335- private class DefaultTypeBodySpec extends ResponseSpecSupport implements TypeBodySpec {
355+ private class DefaultTypeBodySpec implements TypeBodySpec {
356+
357+ private final UndecodedExchangeResult exchangeResult ;
336358
337359 private final ResolvableType elementType ;
338360
339361
340- public DefaultTypeBodySpec (DefaultResponseSpec spec , ResolvableType elementType ) {
341- super ( spec . getExchangeResult (), spec . getResponse ()) ;
362+ public DefaultTypeBodySpec (UndecodedExchangeResult result , ResolvableType elementType ) {
363+ this . exchangeResult = result ;
342364 this .elementType = elementType ;
343365 }
344366
345367
346368 @ Override
347369 public SingleValueBodySpec value () {
348- return new DefaultSingleValueBodySpec (this , this .elementType );
370+ EntityExchangeResult <?> completed = this .exchangeResult .consumeSingle (this .elementType );
371+ return new DefaultSingleValueBodySpec (completed );
349372 }
350373
351374 @ Override
@@ -354,59 +377,52 @@ public ListBodySpec list() {
354377 }
355378
356379 @ Override
357- public ListBodySpec list (int elementCount ) {
358- return new DefaultListBodySpec (this , this .elementType , elementCount );
380+ public ListBodySpec list (int count ) {
381+ EntityExchangeResult <List <?>> completed = this .exchangeResult .consumeList (this .elementType , count );
382+ return new DefaultListBodySpec (completed );
359383 }
360384
361385 @ Override
362- public <T > ExchangeResult <Flux <T >> returnResult () {
363- Flux <T > flux = getResponse ().body (toFlux (this .elementType ));
364- return createResultWithDecodedBody (flux );
386+ public <T > FluxExchangeResult <T > returnResult () {
387+ return this .exchangeResult .decodeBody (this .elementType );
365388 }
366389 }
367390
368- private class DefaultSingleValueBodySpec extends ResponseSpecSupport implements SingleValueBodySpec {
391+ private class DefaultSingleValueBodySpec implements SingleValueBodySpec {
369392
370- private final Object body ;
393+ private final EntityExchangeResult <?> exchangeResult ;
371394
372395
373- public DefaultSingleValueBodySpec (DefaultTypeBodySpec spec , ResolvableType elementType ) {
374- super (spec .getExchangeResult (), spec .getResponse ());
375- this .body = getResponse ().body (toMono (elementType )).block (getTimeout ());
396+ public DefaultSingleValueBodySpec (EntityExchangeResult <?> result ) {
397+ this .exchangeResult = result ;
376398 }
377399
378400
379401 @ Override
380- public <T > ExchangeResult <T > isEqualTo (Object expected ) {
381- assertEquals ("Response body" , expected , this .body );
402+ public <T > EntityExchangeResult <T > isEqualTo (T expected ) {
403+ assertEquals ("Response body" , expected , this .exchangeResult . getResponseBody () );
382404 return returnResult ();
383405 }
384406
385407 @ Override
386- @ SuppressWarnings ("unchecked" )
387- public <T > ExchangeResult <T > returnResult () {
388- return createResultWithDecodedBody ((T ) this .body );
408+ public <T > EntityExchangeResult <T > returnResult () {
409+ return new EntityExchangeResult <>(this .exchangeResult , (T ) this .exchangeResult .getResponseBody ());
389410 }
390411 }
391412
392- private class DefaultListBodySpec extends ResponseSpecSupport implements ListBodySpec {
413+ private class DefaultListBodySpec implements ListBodySpec {
393414
394- private final List <?> body ;
415+ private final EntityExchangeResult < List <?>> exchangeResult ;
395416
396417
397- public DefaultListBodySpec (DefaultTypeBodySpec spec , ResolvableType elementType , int elementCount ) {
398- super (spec .getExchangeResult (), spec .getResponse ());
399- Flux <?> flux = getResponse ().body (toFlux (elementType ));
400- if (elementCount >= 0 ) {
401- flux = flux .take (elementCount );
402- }
403- this .body = flux .collectList ().block (getTimeout ());
418+ public DefaultListBodySpec (EntityExchangeResult <List <?>> result ) {
419+ this .exchangeResult = result ;
404420 }
405421
406422
407423 @ Override
408- public <T > ExchangeResult <List <T >> isEqualTo (List <T > expected ) {
409- assertEquals ("Response body" , expected , this .body );
424+ public <T > EntityExchangeResult <List <T >> isEqualTo (List <T > expected ) {
425+ assertEquals ("Response body" , expected , this .exchangeResult . getResponseBody () );
410426 return returnResult ();
411427 }
412428
@@ -419,38 +435,38 @@ public ListBodySpec hasSize(int size) {
419435 public ListBodySpec contains (Object ... elements ) {
420436 List <Object > elementList = Arrays .asList (elements );
421437 String message = "Response body does not contain " + elementList ;
422- assertTrue (message , this .body .containsAll (elementList ));
438+ assertTrue (message , this .exchangeResult . getResponseBody () .containsAll (elementList ));
423439 return this ;
424440 }
425441
426442 @ Override
427443 public ListBodySpec doesNotContain (Object ... elements ) {
428444 List <Object > elementList = Arrays .asList (elements );
429445 String message = "Response body should have contained " + elementList ;
430- assertTrue (message , !this .body .containsAll (Arrays .asList (elements )));
446+ assertTrue (message , !this .exchangeResult . getResponseBody () .containsAll (Arrays .asList (elements )));
431447 return this ;
432448 }
433449
434450 @ Override
435451 @ SuppressWarnings ("unchecked" )
436- public <T > ExchangeResult <List <T >> returnResult () {
437- return createResultWithDecodedBody ( (List <T >) this .body );
452+ public <T > EntityExchangeResult <List <T >> returnResult () {
453+ return new EntityExchangeResult <>( this . exchangeResult , (List <T >) this .exchangeResult . getResponseBody () );
438454 }
439455 }
440456
441- private class DefaultBodySpec extends ResponseSpecSupport implements BodySpec {
457+ private class DefaultBodySpec implements BodySpec {
458+
459+ private final UndecodedExchangeResult exchangeResult ;
442460
443461
444- public DefaultBodySpec (DefaultResponseSpec spec ) {
445- super ( spec . getExchangeResult (), spec . getResponse ()) ;
462+ public DefaultBodySpec (UndecodedExchangeResult result ) {
463+ this . exchangeResult = result ;
446464 }
447465
448466
449467 @ Override
450- public ExchangeResult <Void > isEmpty () {
451- DataBuffer buffer = getResponse ().body (toDataBuffers ()).blockFirst (getTimeout ());
452- assertTrue ("Expected empty body" , buffer == null );
453- return createResultWithDecodedBody (null );
468+ public EntityExchangeResult <Void > isEmpty () {
469+ return this .exchangeResult .consumeEmpty ();
454470 }
455471
456472 @ Override
@@ -460,57 +476,61 @@ public MapBodySpec map(Class<?> keyType, Class<?> valueType) {
460476
461477 @ Override
462478 public MapBodySpec map (ResolvableType keyType , ResolvableType valueType ) {
463- return new DefaultMapBodySpec (this , keyType , valueType );
479+ EntityExchangeResult <Map <?, ?>> completed = this .exchangeResult .consumeMap (keyType , valueType );
480+ return new DefaultMapBodySpec (completed );
464481 }
465482 }
466483
467- private class DefaultMapBodySpec extends ResponseSpecSupport implements MapBodySpec {
484+ private class DefaultMapBodySpec implements MapBodySpec {
468485
469- private final Map <?, ?> body ;
486+ private final EntityExchangeResult < Map <?, ?>> exchangeResult ;
470487
471488
472- public DefaultMapBodySpec (DefaultBodySpec spec , ResolvableType keyType , ResolvableType valueType ) {
473- super (spec .getExchangeResult (), spec .getResponse ());
474- ResolvableType mapType = ResolvableType .forClassWithGenerics (Map .class , keyType , valueType );
475- this .body = (Map <?, ?>) spec .getResponse ().body (toMono (mapType )).block (getTimeout ());
489+ public DefaultMapBodySpec (EntityExchangeResult <Map <?, ?>> result ) {
490+ this .exchangeResult = result ;
476491 }
477492
478493
494+ private Map <?, ?> getBody () {
495+ return this .exchangeResult .getResponseBody ();
496+ }
497+
479498 @ Override
480- public <K , V > ExchangeResult <Map <K , V >> isEqualTo (Map <K , V > expected ) {
499+ public <K , V > EntityExchangeResult <Map <K , V >> isEqualTo (Map <K , V > expected ) {
500+ assertEquals ("Response body map" , expected , getBody ());
481501 return returnResult ();
482502 }
483503
484504 @ Override
485505 public MapBodySpec hasSize (int size ) {
486- assertEquals ("Response body map size" , size , this . body .size ());
506+ assertEquals ("Response body map size" , size , getBody () .size ());
487507 return this ;
488508 }
489509
490510 @ Override
491511 public MapBodySpec contains (Object key , Object value ) {
492- assertEquals ("Response body map value for key " + key , value , this . body .get (key ));
512+ assertEquals ("Response body map value for key " + key , value , getBody () .get (key ));
493513 return this ;
494514 }
495515
496516 @ Override
497517 public MapBodySpec containsKeys (Object ... keys ) {
498- List <?> missing = Arrays .stream (keys ).filter (k -> !this . body .containsKey (k )).collect (toList ());
518+ List <?> missing = Arrays .stream (keys ).filter (k -> !getBody () .containsKey (k )).collect (toList ());
499519 assertTrue ("Response body map does not contain keys " + missing , missing .isEmpty ());
500520 return this ;
501521 }
502522
503523 @ Override
504524 public MapBodySpec containsValues (Object ... values ) {
505- List <?> missing = Arrays .stream (values ).filter (v -> !this . body .containsValue (v )).collect (toList ());
525+ List <?> missing = Arrays .stream (values ).filter (v -> !getBody () .containsValue (v )).collect (toList ());
506526 assertTrue ("Response body map does not contain values " + missing , missing .isEmpty ());
507527 return this ;
508528 }
509529
510530 @ Override
511531 @ SuppressWarnings ("unchecked" )
512- public <K , V > ExchangeResult <Map <K , V >> returnResult () {
513- return createResultWithDecodedBody ( (Map <K , V >) this . body );
532+ public <K , V > EntityExchangeResult <Map <K , V >> returnResult () {
533+ return new EntityExchangeResult <>( this . exchangeResult , (Map <K , V >) getBody () );
514534 }
515535 }
516536
0 commit comments