RestController throws different exceptions for other errors
[demos/testing] / src / test / java / de / juplo / demo / RestControllerTest.java
1 package de.juplo.demo;
2
3
4 import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
5 import org.junit.jupiter.api.BeforeEach;
6 import org.junit.jupiter.api.DisplayName;
7 import org.junit.jupiter.api.Test;
8 import org.junit.jupiter.params.ParameterizedTest;
9 import org.junit.jupiter.params.provider.EnumSource;
10 import org.mockito.Mockito;
11 import static org.mockito.Mockito.when;
12 import org.springframework.http.HttpStatus;
13 import org.springframework.web.reactive.function.client.WebClientResponseException;
14 import org.springframework.web.reactive.function.client.WebClientResponseException.InternalServerError;
15 import org.springframework.web.reactive.function.client.WebClientResponseException.NotFound;
16 import org.springframework.web.reactive.function.client.WebClientResponseException.ServiceUnavailable;
17 import reactor.core.publisher.Mono;
18 import reactor.test.StepVerifier;
19
20
21 /**
22  * Unit-Test for class {@link RestController}.
23  * @author Kai Moritz
24  */
25 public class RestControllerTest
26 {
27   RestController controller;
28   RemoteContentService service;
29
30
31   @BeforeEach
32   void setUp()
33   {
34     service = Mockito.mock(RemoteContentService.class);
35     controller = new RestController(service);
36   }
37
38
39   @Test
40   @DisplayName("Data successfully fetched from remote-server")
41   void testResponseOK()
42   {
43     when(service.getRemoteText("foo")).thenReturn(Mono.just("bar"));
44
45     Mono<String> result = controller.fetch("foo");
46
47     StepVerifier
48         .create(result)
49         .expectNext("bar")
50         .expectComplete()
51         .verify();
52   }
53
54   @Test
55   @DisplayName("Data not found on remote-server")
56   void testResponseNotFoud()
57   {
58     when(service.getRemoteText("foo")).thenReturn(Mono.error(exception(404)));
59
60     Mono<String> result = controller.fetch("foo");
61
62     StepVerifier
63         .create(result)
64         .expectError(NotFound.class)
65         .verify();
66   }
67
68   /**
69    * Only the behavior on the common errors, as defined in {@link
70    * WebClientResponseException#create(int, String, org.springframework.http.HttpHeaders, byte[], java.nio.charset.Charset, org.springframework.http.HttpRequest)
71    * WebClientResponseException.create()} is tested.
72    */
73   @DisplayName("Other error while fetching data from remote-server")
74   @ParameterizedTest(name = "{arguments} ==> HTTP-status={0}")
75   @EnumSource(value = HttpStatus.class, names = {
76     "BAD_REQUEST",
77     "UNAUTHORIZED",
78     "FORBIDDEN",
79     "METHOD_NOT_ALLOWED",
80     "NOT_ACCEPTABLE",
81     "CONFLICT",
82     "GONE",
83     "UNSUPPORTED_MEDIA_TYPE",
84     "TOO_MANY_REQUESTS",
85     "UNPROCESSABLE_ENTITY",
86     "INTERNAL_SERVER_ERROR",
87     "NOT_IMPLEMENTED",
88     "BAD_GATEWAY",
89     "SERVICE_UNAVAILABLE",
90     "GATEWAY_TIMEOUT"
91   })
92   void testResponseOtherErrors(HttpStatus status)
93   {
94     Mono<String> mono = Mono.error(exception(status.value()));
95     when(service.getRemoteText("foo")).thenReturn(mono);
96
97     Mono<String> result = controller.fetch("foo");
98
99     StepVerifier
100         .create(result)
101         .expectErrorSatisfies((t) ->
102         {
103           assertThat(t).isInstanceOf(ServiceUnavailable.class);
104           assertThat(t.getMessage())
105               .startsWith(
106                   "503 Service Unavailable - Cause: " +
107                   Integer.toString(status.value()));
108         })
109         .verify();
110   }
111
112   @Test
113   @DisplayName("Internal error while fetching data from remote-server")
114   void testOtherErrors()
115   {
116     Mono<String> mono = Mono.error(new RuntimeException("Boom!"));
117     when(service.getRemoteText("foo")).thenReturn(mono);
118
119     Mono<String> result = controller.fetch("foo");
120
121     StepVerifier
122         .create(result)
123         .expectErrorSatisfies((t) ->
124         {
125           assertThat(t).isInstanceOf(InternalServerError.class);
126           assertThat(t.getMessage()).isEqualTo("500 Internal Server Error - Cause: Boom!");
127         })
128         .verify();
129   }
130
131
132   WebClientResponseException exception(int status)
133   {
134     return WebClientResponseException.create(status, "", null, null, null);
135   }
136 }