20
20
import java .io .PrintStream ;
21
21
import java .io .StringWriter ;
22
22
import java .nio .charset .StandardCharsets ;
23
+ import java .time .Duration ;
23
24
import java .util .Collections ;
24
25
import java .util .HashMap ;
25
26
import java .util .List ;
36
37
import jakarta .servlet .http .Part ;
37
38
import jakarta .validation .Valid ;
38
39
import jakarta .validation .constraints .Size ;
40
+ import org .assertj .core .api .InstanceOfAssertFactories ;
39
41
import org .junit .jupiter .api .AfterEach ;
40
42
import org .junit .jupiter .api .BeforeEach ;
41
43
import org .junit .jupiter .api .Nested ;
53
55
import org .springframework .test .context .junit .jupiter .web .SpringJUnitWebConfig ;
54
56
import org .springframework .test .web .Person ;
55
57
import org .springframework .test .web .servlet .ResultMatcher ;
58
+ import org .springframework .test .web .servlet .assertj .MockMvcTester .MockMvcRequestBuilder ;
56
59
import org .springframework .ui .Model ;
57
60
import org .springframework .validation .Errors ;
58
61
import org .springframework .web .bind .annotation .GetMapping ;
73
76
import org .springframework .web .servlet .HandlerInterceptor ;
74
77
import org .springframework .web .servlet .ModelAndView ;
75
78
import org .springframework .web .servlet .config .annotation .EnableWebMvc ;
79
+ import org .springframework .web .servlet .mvc .method .annotation .StreamingResponseBody ;
76
80
import org .springframework .web .servlet .mvc .support .RedirectAttributes ;
77
81
78
82
import static java .util .Map .entry ;
79
83
import static org .assertj .core .api .Assertions .assertThat ;
80
84
import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
81
- import static org .assertj .core .api .InstanceOfAssertFactories . map ;
85
+ import static org .assertj .core .api .Assertions . assertThatIllegalStateException ;
82
86
import static org .mockito .Mockito .mock ;
83
87
import static org .mockito .Mockito .verify ;
88
+ import static org .mockito .Mockito .verifyNoInteractions ;
84
89
85
90
/**
86
91
* Integration tests for {@link MockMvcTester}.
@@ -97,12 +102,60 @@ public class MockMvcTesterIntegrationTests {
97
102
this .mvc = MockMvcTester .from (wac );
98
103
}
99
104
105
+ @ Nested
106
+ class PerformTests {
107
+
108
+ @ Test
109
+ void syncRequestWithDefaultExchange () {
110
+ assertThat (mvc .get ().uri ("/greet" )).hasStatusOk ();
111
+ }
112
+
113
+ @ Test
114
+ void asyncRequestWithDefaultExchange () {
115
+ assertThat (mvc .get ().uri ("/streaming" ).param ("timeToWait" , "100" )).hasStatusOk ()
116
+ .hasBodyTextEqualTo ("name=Joe&someBoolean=true" );
117
+ }
118
+
119
+ @ Test
120
+ void syncRequestWithExplicitExchange () {
121
+ assertThat (mvc .get ().uri ("/greet" ).exchange ()).hasStatusOk ();
122
+ }
123
+
124
+ @ Test
125
+ void asyncRequestWithExplicitExchange () {
126
+ assertThat (mvc .get ().uri ("/streaming" ).param ("timeToWait" , "100" ).exchange ())
127
+ .hasStatusOk ().hasBodyTextEqualTo ("name=Joe&someBoolean=true" );
128
+ }
129
+
130
+ @ Test
131
+ void syncRequestWithExplicitExchangeIgnoresDuration () {
132
+ Duration timeToWait = mock (Duration .class );
133
+ assertThat (mvc .get ().uri ("/greet" ).exchange (timeToWait )).hasStatusOk ();
134
+ verifyNoInteractions (timeToWait );
135
+ }
136
+
137
+ @ Test
138
+ void asyncRequestWithExplicitExchangeAndEnoughTimeToWait () {
139
+ assertThat (mvc .get ().uri ("/streaming" ).param ("timeToWait" , "100" ).exchange (Duration .ofMillis (200 )))
140
+ .hasStatusOk ().hasBodyTextEqualTo ("name=Joe&someBoolean=true" );
141
+ }
142
+
143
+ @ Test
144
+ void asyncRequestWithExplicitExchangeAndNotEnoughTimeToWait () {
145
+ MockMvcRequestBuilder builder = mvc .get ().uri ("/streaming" ).param ("timeToWait" , "500" );
146
+ assertThatIllegalStateException ()
147
+ .isThrownBy (() -> builder .exchange (Duration .ofMillis (100 )))
148
+ .withMessageContaining ("was not set during the specified timeToWait=100" );
149
+ }
150
+ }
151
+
100
152
@ Nested
101
153
class RequestTests {
102
154
103
155
@ Test
104
156
void hasAsyncStartedTrue () {
105
- assertThat (mvc .get ().uri ("/callable" ).accept (MediaType .APPLICATION_JSON ))
157
+ // Need #perform as the regular exchange waits for async completion automatically
158
+ assertThat (mvc .perform (mvc .get ().uri ("/callable" ).accept (MediaType .APPLICATION_JSON )))
106
159
.request ().hasAsyncStarted (true );
107
160
}
108
161
@@ -272,8 +325,10 @@ class BodyTests {
272
325
273
326
@ Test
274
327
void asyncResult () {
275
- assertThat (mvc .get ().uri ("/callable" ).accept (MediaType .APPLICATION_JSON ))
276
- .asyncResult ().asInstanceOf (map (String .class , Object .class ))
328
+ // Need #perform as the regular exchange waits for async completion automatically
329
+ MvcTestResult result = mvc .perform (mvc .get ().uri ("/callable" ).accept (MediaType .APPLICATION_JSON ));
330
+ assertThat (result .getMvcResult ().getAsyncResult ())
331
+ .asInstanceOf (InstanceOfAssertFactories .map (String .class , Object .class ))
277
332
.containsOnly (entry ("key" , "value" ));
278
333
}
279
334
@@ -441,12 +496,6 @@ void assertAndApplyWithUnresolvedException() {
441
496
result -> assertThat (result ).apply (mvcResult -> {}));
442
497
}
443
498
444
- @ Test
445
- void assertAsyncResultWithUnresolvedException () {
446
- testAssertionFailureWithUnresolvableException (
447
- result -> assertThat (result ).asyncResult ());
448
- }
449
-
450
499
@ Test
451
500
void assertContentTypeWithUnresolvedException () {
452
501
testAssertionFailureWithUnresolvableException (
@@ -617,6 +666,21 @@ static class AsyncController {
617
666
public Callable <Map <String , String >> getCallable () {
618
667
return () -> Collections .singletonMap ("key" , "value" );
619
668
}
669
+
670
+ @ GetMapping ("/streaming" )
671
+ StreamingResponseBody streaming (@ RequestParam long timeToWait ) {
672
+ return out -> {
673
+ PrintStream stream = new PrintStream (out , true , StandardCharsets .UTF_8 );
674
+ stream .print ("name=Joe" );
675
+ try {
676
+ Thread .sleep (timeToWait );
677
+ stream .print ("&someBoolean=true" );
678
+ }
679
+ catch (InterruptedException e ) {
680
+ /* no-op */
681
+ }
682
+ };
683
+ }
620
684
}
621
685
622
686
@ Controller
0 commit comments