1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.exception.spring.boot.autoconfigure.servlet;
18
19 import static org.assertj.core.api.Assertions.assertThatThrownBy;
20
21 import feign.Contract;
22 import feign.Feign;
23 import feign.codec.Decoder;
24 import feign.codec.Encoder;
25 import feign.okhttp.OkHttpClient;
26 import java.time.OffsetDateTime;
27 import org.assertj.core.api.junit.jupiter.SoftAssertionsExtension;
28 import org.bremersee.exception.RestApiResponseException;
29 import org.bremersee.exception.feign.FeignClientException;
30 import org.bremersee.exception.feign.FeignClientExceptionErrorDecoder;
31 import org.bremersee.exception.model.RestApiException;
32 import org.bremersee.exception.spring.boot.autoconfigure.servlet.app.TestConfiguration;
33 import org.bremersee.exception.spring.boot.autoconfigure.servlet.app.TestConfiguration.TestRestController;
34 import org.junit.jupiter.api.Test;
35 import org.junit.jupiter.api.extension.ExtendWith;
36 import org.springframework.beans.factory.annotation.Autowired;
37 import org.springframework.boot.test.context.SpringBootTest;
38 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
39 import org.springframework.boot.test.web.server.LocalServerPort;
40 import org.springframework.boot.web.client.RestTemplateBuilder;
41 import org.springframework.cloud.openfeign.FeignClientsConfiguration;
42 import org.springframework.http.HttpStatus;
43
44
45
46
47
48
49 @SpringBootTest(
50 classes = {TestConfiguration.class, FeignClientsConfiguration.class},
51 webEnvironment = WebEnvironment.RANDOM_PORT,
52 properties = {
53 "spring.main.web-application-type=servlet",
54 "spring.application.name=test",
55 "bremersee.exception-mapping.api-paths=/api/**"
56 }
57 )
58 @ExtendWith(SoftAssertionsExtension.class)
59 class ServletIntegrationTest {
60
61
62
63
64 @Autowired
65 RestTemplateBuilder restTemplateBuilder;
66
67
68
69
70 @Autowired
71 Contract contract;
72
73
74
75
76 @Autowired
77 Encoder encoder;
78
79
80
81
82 @Autowired
83 Decoder decoder;
84
85
86
87
88 @Autowired
89 FeignClientExceptionErrorDecoder feignClientExceptionErrorDecoder;
90
91
92
93
94 @LocalServerPort
95 int port;
96
97
98
99
100
101
102 String baseUrl() {
103 return "http://localhost:" + port;
104 }
105
106
107
108
109 @Test
110 void fetchRestApiException() {
111 RestApiException expected = RestApiException.builder()
112 .status(HttpStatus.CONFLICT.value())
113 .error(HttpStatus.CONFLICT.getReasonPhrase())
114 .errorCode("1234")
115 .errorCodeInherited(false)
116 .message("Entity with identifier [MyEntity] already exists.")
117 .exception("org.bremersee.exception.ServiceException")
118 .application("test")
119 .path("/api/exception")
120 .build();
121
122 assertThatThrownBy(() -> restTemplateBuilder.build()
123 .getForEntity(baseUrl() + "/api/exception", String.class)
124 .getBody())
125 .isInstanceOf(RestApiResponseException.class)
126 .extracting(exc -> ((RestApiResponseException) exc).getRestApiException())
127 .usingRecursiveComparison()
128 .ignoringFieldsOfTypes(OffsetDateTime.class)
129 .isEqualTo(expected);
130 }
131
132
133
134
135 @Test
136 void fetchRestApiExceptionWithFeign() {
137 RestApiException expected = RestApiException.builder()
138 .status(HttpStatus.CONFLICT.value())
139 .error(HttpStatus.CONFLICT.getReasonPhrase())
140 .errorCode("1234")
141 .errorCodeInherited(false)
142 .message("Entity with identifier [MyEntity] already exists.")
143 .exception("org.bremersee.exception.ServiceException")
144 .application("test")
145 .path("/api/exception")
146 .build();
147
148 TestRestController proxy = Feign.builder()
149 .client(new OkHttpClient())
150 .contract(contract)
151 .encoder(encoder)
152 .decoder(decoder)
153 .errorDecoder(feignClientExceptionErrorDecoder)
154 .target(TestRestController.class, baseUrl());
155
156 assertThatThrownBy(proxy::throwServiceException)
157 .isInstanceOf(FeignClientException.class)
158 .extracting(exc -> ((FeignClientException) exc).getRestApiException())
159 .usingRecursiveComparison()
160 .ignoringFieldsOfTypes(OffsetDateTime.class)
161 .isEqualTo(expected);
162 }
163
164 }