19
19
import java .util .List ;
20
20
import java .util .Map ;
21
21
22
+ import org .junit .jupiter .api .BeforeEach ;
22
23
import org .junit .jupiter .api .Test ;
24
+ import reactor .core .publisher .Flux ;
23
25
24
26
import org .springframework .context .annotation .AnnotationConfigApplicationContext ;
25
27
import org .springframework .context .annotation .Bean ;
28
30
import org .springframework .core .MethodParameter ;
29
31
import org .springframework .core .ReactiveAdapterRegistry ;
30
32
import org .springframework .core .task .SyncTaskExecutor ;
31
- import org .springframework .http .converter .json .MappingJackson2HttpMessageConverter ;
33
+ import org .springframework .http .HttpHeaders ;
34
+ import org .springframework .http .converter .StringHttpMessageConverter ;
32
35
import org .springframework .web .accept .ContentNegotiationManager ;
33
36
import org .springframework .web .context .request .NativeWebRequest ;
34
37
import org .springframework .web .context .request .ServletWebRequest ;
51
54
*/
52
55
public class FragmentRenderingStreamTests {
53
56
54
- @ Test
55
- void streamFragments () throws Exception {
57
+ private final MockHttpServletRequest request = new MockHttpServletRequest ();
58
+
59
+ private final MockHttpServletResponse response = new MockHttpServletResponse ();
60
+
61
+ private final NativeWebRequest webRequest = new ServletWebRequest (request , response );
62
+
63
+ private ResponseBodyEmitterReturnValueHandler handler ;
64
+
65
+
66
+ @ BeforeEach
67
+ void setUp () {
68
+ AsyncWebRequest asyncWebRequest = new StandardServletAsyncWebRequest (this .request , this .response );
69
+ WebAsyncUtils .getAsyncManager (this .webRequest ).setAsyncWebRequest (asyncWebRequest );
70
+ this .request .setAsyncSupported (true );
56
71
57
72
AnnotationConfigApplicationContext context =
58
73
new AnnotationConfigApplicationContext (ScriptTemplatingConfiguration .class );
@@ -61,44 +76,84 @@ void streamFragments() throws Exception {
61
76
ScriptTemplateViewResolver viewResolver = new ScriptTemplateViewResolver (prefix , ".kts" );
62
77
viewResolver .setApplicationContext (context );
63
78
64
- ResponseBodyEmitterReturnValueHandler handler = new ResponseBodyEmitterReturnValueHandler (
65
- List .of (new MappingJackson2HttpMessageConverter ()),
79
+ this . handler = new ResponseBodyEmitterReturnValueHandler (
80
+ List .of (new StringHttpMessageConverter ()),
66
81
ReactiveAdapterRegistry .getSharedInstance (), new SyncTaskExecutor (),
67
82
new ContentNegotiationManager (),
68
83
List .of (viewResolver ), null );
84
+ }
69
85
70
- MockHttpServletRequest request = new MockHttpServletRequest ();
71
- MockHttpServletResponse response = new MockHttpServletResponse ();
72
- NativeWebRequest webRequest = new ServletWebRequest (request , response );
73
-
74
- AsyncWebRequest asyncWebRequest = new StandardServletAsyncWebRequest (request , response );
75
- WebAsyncUtils .getAsyncManager (webRequest ).setAsyncWebRequest (asyncWebRequest );
76
- request .setAsyncSupported (true );
77
86
87
+ @ Test
88
+ void streamWithSseEmitter () throws Exception {
78
89
MethodParameter type = on (TestController .class ).resolveReturnType (SseEmitter .class );
90
+
79
91
SseEmitter emitter = new SseEmitter ();
80
- handler .handleReturnValue (emitter , type , new ModelAndViewContainer (), webRequest );
92
+ this . handler .handleReturnValue (emitter , type , new ModelAndViewContainer (), webRequest );
81
93
82
- assertThat (request .isAsyncStarted ()).isTrue ();
83
- assertThat (response .getStatus ()).isEqualTo (200 );
94
+ assertThat (this . request .isAsyncStarted ()).isTrue ();
95
+ assertThat (this . response .getStatus ()).isEqualTo (200 );
84
96
85
97
ModelAndView mav1 = new ModelAndView ("fragment1" , Map .of ("foo" , "Foo" ));
86
98
ModelAndView mav2 = new ModelAndView ("fragment2" , Map .of ("bar" , "Bar" ));
87
99
88
- emitter .send (SseEmitter .event ().data (mav1 ).data (mav2 ));
100
+ emitter .send (SseEmitter .event ().data (mav1 ));
101
+ emitter .send (SseEmitter .event ().data (mav2 ));
89
102
90
- assertThat (response .getContentType ()).isEqualTo ("text/event-stream" );
91
- assertThat (response .getContentAsString ()).isEqualTo (("""
92
- data:<p>Hello Foo</p>
93
- data:<p>Hello Bar</p>
103
+ assertThat (this .response .getContentType ()).isEqualTo ("text/event-stream" );
104
+ assertThat (this .response .getContentAsString ()).isEqualTo (("""
105
+ event:fragment1
106
+ data:<p>
107
+ data: Hello Foo
108
+ data:</p>
109
+
110
+ event:fragment2
111
+ data:<p>
112
+ data: Hello Bar
113
+ data:</p>
94
114
95
115
""" ));
96
116
}
97
117
118
+ @ Test
119
+ void streamWithFlux () throws Exception {
120
+ MethodParameter type = on (TestController .class ).resolveReturnType (Flux .class , ModelAndView .class );
121
+
122
+ this .request .addHeader (HttpHeaders .ACCEPT , "text/event-stream" );
98
123
124
+ Flux <ModelAndView > flux = Flux .just (
125
+ new ModelAndView ("fragment1" , Map .of ("foo" , "Foo" )),
126
+ new ModelAndView ("fragment2" , Map .of ("bar" , "Bar" )));
127
+
128
+ this .handler .handleReturnValue (flux , type , new ModelAndViewContainer (), webRequest );
129
+
130
+ assertThat (this .request .isAsyncStarted ()).isTrue ();
131
+ assertThat (this .response .getStatus ()).isEqualTo (200 );
132
+
133
+ assertThat (this .response .getContentType ()).isEqualTo ("text/event-stream" );
134
+ assertThat (this .response .getContentAsString ()).isEqualTo (("""
135
+ event:fragment1
136
+ data:<p>
137
+ data: Hello Foo
138
+ data:</p>
139
+
140
+ event:fragment2
141
+ data:<p>
142
+ data: Hello Bar
143
+ data:</p>
144
+
145
+ """ ));
146
+ }
147
+
148
+
149
+ @ SuppressWarnings ({"unused" , "DataFlowIssue" })
99
150
private static class TestController {
100
151
101
- SseEmitter handle () {
152
+ SseEmitter handleWithSseEmitter () {
153
+ return null ;
154
+ }
155
+
156
+ Flux <ModelAndView > handleWithFlux () {
102
157
return null ;
103
158
}
104
159
}
0 commit comments