WIP
[demos/testing] / src / test / java / de / juplo / demo / RemoteContentServiceTest.java
1 package de.juplo.demo;
2
3
4 import java.net.URI;
5 import java.nio.charset.Charset;
6 import java.time.ZonedDateTime;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.function.Consumer;
10 import java.util.function.Function;
11 import java.util.function.IntPredicate;
12 import java.util.function.Predicate;
13 import java.util.function.Supplier;
14 import org.junit.jupiter.api.BeforeEach;
15 import org.junit.jupiter.api.Test;
16 import org.junit.jupiter.api.extension.ExtendWith;
17 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.when;
19 import org.reactivestreams.Publisher;
20 import org.springframework.boot.test.mock.mockito.MockBean;
21 import org.springframework.core.ParameterizedTypeReference;
22 import org.springframework.http.HttpHeaders;
23 import org.springframework.http.HttpMethod;
24 import org.springframework.http.HttpStatus;
25 import org.springframework.http.MediaType;
26 import org.springframework.http.ResponseEntity;
27 import org.springframework.http.client.reactive.ClientHttpRequest;
28 import org.springframework.test.context.junit.jupiter.SpringExtension;
29 import org.springframework.util.MultiValueMap;
30 import org.springframework.web.reactive.function.BodyInserter;
31 import org.springframework.web.reactive.function.client.ClientResponse;
32 import org.springframework.web.reactive.function.client.WebClient;
33 import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
34 import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec;
35 import org.springframework.web.reactive.function.client.WebClient.ResponseSpec;
36 import org.springframework.web.util.UriBuilder;
37 import reactor.core.publisher.Flux;
38 import reactor.core.publisher.Mono;
39 import reactor.test.StepVerifier;
40
41
42 /**
43  * Unit-Test for class {@link RemoteContentService}.
44  * @author Kai Moritz
45  */
46 @ExtendWith(SpringExtension.class)
47 public class RemoteContentServiceTest
48 {
49   RemoteContentService service;
50
51   @MockBean
52   WebClient webClient;
53   @MockBean(name = "uriSpec")
54   RequestHeadersUriSpec uriSpec;
55   @MockBean(name = "headersSpec")
56   RequestHeadersSpec headersSpec;
57   @MockBean(name = "responseSpec")
58   ResponseSpec responseSpec;
59
60
61   @BeforeEach
62   void setUp()
63   {
64     service = new RemoteContentService(webClient);
65   }
66
67
68   @Test
69   void test()
70   {
71     when(webClient.get()).thenReturn(uriSpec);
72     when(uriSpec.uri(eq("/foo"))).thenReturn(headersSpec);
73     when(headersSpec.retrieve()).thenReturn(responseSpec);
74     when(responseSpec.bodyToMono(String.class)).thenReturn(Mono.just("bar"));
75
76     Mono<String> result = service.getRemoteText("/foo");
77
78     StepVerifier
79         .create(result)
80         .expectNext("bar")
81         .verifyComplete();
82   }
83
84
85   static class WebClientStub implements WebClient
86   {
87     final static WebClientStub WEB_CLIENT = new WebClientStub();
88     final static RequestHeadersUriSpecStub HEADERS_SPEC = new RequestHeadersUriSpecStub();
89     final static RequestBodySpecStub REQUEST_BODY_SPEC = new RequestBodySpecStub();
90     final static ResponseSpecStub RESPONSE_SPEC = new ResponseSpecStub();
91
92     static Supplier<Mono<?>> toMono;
93     static Supplier<Flux<?>> toFlux;
94
95
96     private WebClientStub() {}
97
98
99     @Override
100     public RequestHeadersUriSpec<?> get()
101     {
102       return HEADERS_SPEC;
103     }
104
105     @Override
106     public RequestHeadersUriSpec<?> head()
107     {
108       return HEADERS_SPEC;
109     }
110
111     @Override
112     public RequestBodyUriSpec post()
113     {
114       return REQUEST_BODY_SPEC;
115     }
116
117     @Override
118     public RequestBodyUriSpec put()
119     {
120       return REQUEST_BODY_SPEC;
121     }
122
123     @Override
124     public RequestBodyUriSpec patch()
125     {
126       return REQUEST_BODY_SPEC;
127     }
128
129     @Override
130     public RequestHeadersUriSpec<?> delete()
131     {
132       return HEADERS_SPEC;
133     }
134
135     @Override
136     public RequestHeadersUriSpec<?> options()
137     {
138       return HEADERS_SPEC;
139     }
140
141     @Override
142     public RequestBodyUriSpec method(HttpMethod hm)
143     {
144       return REQUEST_BODY_SPEC;
145     }
146
147     @Override
148     public Builder mutate()
149     {
150       throw new UnsupportedOperationException("Stub is immutable!");
151     }
152
153
154     static class RequestHeadersUriSpecStub implements RequestHeadersUriSpec
155     {
156       private RequestHeadersUriSpecStub() {}
157
158
159       @Override
160       public RequestHeadersSpec uri(URI uri)
161       {
162         return this;
163       }
164
165       @Override
166       public RequestHeadersSpec uri(String string, Object... os)
167       {
168         return this;
169       }
170
171       @Override
172       public RequestHeadersSpec uri(String string, Map map)
173       {
174         return this;
175       }
176
177       @Override
178       public RequestHeadersSpec uri(String string, Function fnctn)
179       {
180         return this;
181       }
182
183       @Override
184       public RequestHeadersSpec uri(Function fnctn)
185       {
186         return this;
187       }
188
189       @Override
190       public RequestHeadersSpec accept(MediaType... mts)
191       {
192         return this;
193       }
194
195       @Override
196       public RequestHeadersSpec acceptCharset(Charset... chrsts)
197       {
198         return this;
199       }
200
201       @Override
202       public RequestHeadersSpec cookie(String string, String string1)
203       {
204         return this;
205       }
206
207       @Override
208       public RequestHeadersSpec cookies(Consumer cnsmr)
209       {
210         return this;
211       }
212
213       @Override
214       public RequestHeadersSpec ifModifiedSince(ZonedDateTime zdt)
215       {
216         return this;
217       }
218
219       @Override
220       public RequestHeadersSpec ifNoneMatch(String... strings)
221       {
222         return this;
223       }
224
225       @Override
226       public RequestHeadersSpec header(String string, String... strings)
227       {
228         return this;
229       }
230
231       @Override
232       public RequestHeadersSpec headers(Consumer cnsmr)
233       {
234         return this;
235       }
236
237       @Override
238       public RequestHeadersSpec attribute(String string, Object o)
239       {
240         return this;
241       }
242
243       @Override
244       public RequestHeadersSpec attributes(Consumer cnsmr)
245       {
246         return this;
247       }
248
249       @Override
250       public ResponseSpec retrieve()
251       {
252         return RESPONSE_SPEC;
253       }
254
255       @Override
256       public Mono exchange()
257       {
258         return WebClientStub.toMono.get();
259       }
260     }
261
262     static class RequestBodySpecStub implements RequestBodyUriSpec
263     {
264       private RequestBodySpecStub() {}
265
266
267       @Override
268       public RequestBodySpec contentLength(long l)
269       {
270         return this;
271       }
272
273       @Override
274       public RequestBodySpec contentType(MediaType mt)
275       {
276         return this;
277       }
278
279       @Override
280       public RequestHeadersSpec<?> bodyValue(Object o)
281       {
282         return this;
283       }
284
285       @Override
286       public <T, P extends Publisher<T>> RequestHeadersSpec<?> body(P p, Class<T> type)
287       {
288         return this;
289       }
290
291       @Override
292       public <T, P extends Publisher<T>> RequestHeadersSpec<?> body(P p, ParameterizedTypeReference<T> ptr)
293       {
294         return this;
295       }
296
297       @Override
298       public RequestHeadersSpec<?> body(Object o, Class<?> type)
299       {
300         return this;
301       }
302
303       @Override
304       public RequestHeadersSpec<?> body(Object o, ParameterizedTypeReference<?> ptr)
305       {
306         return this;
307       }
308
309       @Override
310       public RequestHeadersSpec<?> body( BodyInserter<?, ? super ClientHttpRequest> bi)
311       {
312         return this;
313       }
314
315       @Override
316       public RequestHeadersSpec<?> syncBody(Object o)
317       {
318         return this;
319       }
320
321       @Override
322       public RequestBodySpec accept(MediaType... mts)
323       {
324         return this;
325       }
326
327       @Override
328       public RequestBodySpec acceptCharset(Charset... chrsts)
329       {
330         return this;
331       }
332
333       @Override
334       public RequestBodySpec cookie(String string, String string1)
335       {
336         return this;
337       }
338
339       @Override
340       public RequestBodySpec cookies(Consumer<MultiValueMap<String, String>> cnsmr)
341       {
342         return this;
343       }
344
345       @Override
346       public RequestBodySpec ifModifiedSince(ZonedDateTime zdt)
347       {
348         return this;
349       }
350
351       @Override
352       public RequestBodySpec ifNoneMatch(String... strings)
353       {
354         return this;
355       }
356
357       @Override
358       public RequestBodySpec header(String string, String... strings)
359       {
360         return this;
361       }
362
363       @Override
364       public RequestBodySpec headers(Consumer<HttpHeaders> cnsmr)
365       {
366         return this;
367       }
368
369       @Override
370       public RequestBodySpec attribute(String string, Object o)
371       {
372         return this;
373       }
374
375       @Override
376       public RequestBodySpec attributes(Consumer<Map<String, Object>> cnsmr)
377       {
378         return this;
379       }
380
381       @Override
382       public ResponseSpec retrieve()
383       {
384         throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
385       }
386
387       @Override
388       public Mono<ClientResponse> exchange()
389       {
390         throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
391       }
392
393       @Override
394       public RequestBodySpec uri(URI uri)
395       {
396         return this;
397       }
398
399       @Override
400       public RequestBodySpec uri(String string, Object... os)
401       {
402         return this;
403       }
404
405       @Override
406       public RequestBodySpec uri(String string, Map<String, ?> map)
407       {
408         return this;
409       }
410
411       @Override
412       public RequestBodySpec uri(String string, Function<UriBuilder, URI> fnctn)
413       {
414         return this;
415       }
416
417       @Override
418       public RequestBodySpec uri(Function<UriBuilder, URI> fnctn)
419       {
420         return this;
421       }
422     }
423
424     static class ResponseSpecStub implements ResponseSpec
425     {
426       private ResponseSpecStub() {}
427
428
429       @Override
430       public ResponseSpec onStatus(Predicate<HttpStatus> statusPredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction)
431       {
432         return this;
433       }
434
435       @Override
436       public ResponseSpec onRawStatus(IntPredicate statusCodePredicate, Function<ClientResponse, Mono<? extends Throwable>> exceptionFunction)
437       {
438         return this;
439       }
440
441       @Override
442       public <T> Mono<T> bodyToMono(Class<T> elementClass)
443       {
444         return (Mono<T>)toMono.get();
445       }
446
447       @Override
448       public <T> Mono<T> bodyToMono(ParameterizedTypeReference<T> elementTypeRef)
449       {
450         return (Mono<T>)toMono.get();
451       }
452
453       @Override
454       public <T> Flux<T> bodyToFlux(Class<T> elementClass)
455       {
456         return (Flux<T>)toFlux;
457       }
458
459       @Override
460       public <T> Flux<T> bodyToFlux(ParameterizedTypeReference<T> elementTypeRef)
461       {
462         return (Flux<T>)toFlux;
463       }
464
465       @Override
466       public <T> Mono<ResponseEntity<T>> toEntity(Class<T> bodyClass)
467       {
468         return (Mono<ResponseEntity<T>>)toMono.get();
469       }
470
471       @Override
472       public <T> Mono<ResponseEntity<T>> toEntity(ParameterizedTypeReference<T> bodyTypeReference)
473       {
474         return (Mono<ResponseEntity<T>>)toMono.get();
475       }
476
477       @Override
478       public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> elementClass)
479       {
480         return (Mono<ResponseEntity<List<T>>>)toMono.get();
481       }
482
483       @Override
484       public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> elementTypeRef)
485       {
486         return (Mono<ResponseEntity<List<T>>>)toMono.get();
487       }
488
489       @Override
490       public Mono<ResponseEntity<Void>> toBodilessEntity()
491       {
492         return (Mono<ResponseEntity<Void>>)toMono.get();
493       }
494     }
495   }
496 }