2 * ========================LICENSE_START=================================
4 * ======================================================================
5 * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved.
6 * ======================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ========================LICENSE_END===================================
21 package org.oransc.enrichment;
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.jupiter.api.Assertions.assertTrue;
27 import com.fasterxml.jackson.core.JsonProcessingException;
28 import com.fasterxml.jackson.databind.JsonMappingException;
29 import com.google.gson.Gson;
30 import com.google.gson.GsonBuilder;
31 import com.google.gson.JsonParser;
33 import java.util.ArrayList;
34 import java.util.Collection;
36 import org.junit.jupiter.api.AfterEach;
37 import org.junit.jupiter.api.BeforeEach;
38 import org.junit.jupiter.api.Test;
39 import org.junit.jupiter.api.extension.ExtendWith;
40 import org.oransc.enrichment.clients.AsyncRestClient;
41 import org.oransc.enrichment.clients.ProducerJobInfo;
42 import org.oransc.enrichment.configuration.ApplicationConfig;
43 import org.oransc.enrichment.configuration.ImmutableWebClientConfig;
44 import org.oransc.enrichment.configuration.WebClientConfig;
45 import org.oransc.enrichment.controller.ProducerSimulatorController;
46 import org.oransc.enrichment.controllers.consumer.ConsumerConsts;
47 import org.oransc.enrichment.controllers.consumer.ConsumerEiJobInfo;
48 import org.oransc.enrichment.controllers.consumer.ConsumerEiTypeInfo;
49 import org.oransc.enrichment.controllers.producer.ProducerConsts;
50 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo;
51 import org.oransc.enrichment.controllers.producer.ProducerRegistrationInfo.ProducerEiTypeRegistrationInfo;
52 import org.oransc.enrichment.exceptions.ServiceException;
53 import org.oransc.enrichment.repository.EiJob;
54 import org.oransc.enrichment.repository.EiJobs;
55 import org.oransc.enrichment.repository.EiProducers;
56 import org.oransc.enrichment.repository.EiType;
57 import org.oransc.enrichment.repository.EiTypes;
58 import org.springframework.beans.factory.annotation.Autowired;
59 import org.springframework.boot.test.context.SpringBootTest;
60 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
61 import org.springframework.boot.test.context.TestConfiguration;
62 import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
63 import org.springframework.boot.web.server.LocalServerPort;
64 import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
65 import org.springframework.context.ApplicationContext;
66 import org.springframework.context.annotation.Bean;
67 import org.springframework.http.HttpStatus;
68 import org.springframework.http.MediaType;
69 import org.springframework.http.ResponseEntity;
70 import org.springframework.test.context.TestPropertySource;
71 import org.springframework.test.context.junit.jupiter.SpringExtension;
72 import org.springframework.web.reactive.function.client.WebClientResponseException;
74 import reactor.core.publisher.Mono;
75 import reactor.test.StepVerifier;
77 @ExtendWith(SpringExtension.class)
78 @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
81 "server.ssl.key-store=./config/keystore.jks", //
82 "app.webclient.trust-store=./config/truststore.jks"})
83 class ApplicationTest {
84 private final String EI_TYPE_ID = "typeId";
85 private final String EI_PRODUCER_ID = "producerId";
86 private final String EI_JOB_PROPERTY = "\"property1\"";
89 ApplicationContext context;
98 EiProducers eiProducers;
101 ApplicationConfig applicationConfig;
104 ProducerSimulatorController producerSimulator;
106 private static Gson gson = new GsonBuilder() //
111 * Overrides the BeanFactory.
114 static class TestBeanFactory {
116 public ServletWebServerFactory servletContainer() {
117 return new TomcatServletWebServerFactory();
127 this.eiTypes.clear();
128 this.eiProducers.clear();
129 this.producerSimulator.getTestResults().reset();
134 assertThat(this.producerSimulator.getTestResults().errorFound).isFalse();
138 void testGetEiTypes() throws Exception {
139 putEiProducerWithOneType(EI_PRODUCER_ID, "test");
140 String url = ConsumerConsts.API_ROOT + "/eitypes";
141 String rsp = restClient().get(url).block();
142 assertThat(rsp).isEqualTo("[\"test\"]");
146 void testGetEiType() throws Exception {
147 putEiProducerWithOneType(EI_PRODUCER_ID, "test");
148 String url = ConsumerConsts.API_ROOT + "/eitypes/test";
149 String rsp = restClient().get(url).block();
150 ConsumerEiTypeInfo info = gson.fromJson(rsp, ConsumerEiTypeInfo.class);
151 assertThat(info.jobParametersSchema).isNotNull();
155 void testGetEiTypeNotFound() throws Exception {
156 String url = ConsumerConsts.API_ROOT + "/eitypes/junk";
157 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
161 void testGetEiJobsIds() throws Exception {
162 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
163 putEiJob(EI_TYPE_ID, "jobId");
164 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs";
165 String rsp = restClient().get(url).block();
166 assertThat(rsp).isEqualTo("[\"jobId\"]");
170 void testGetEiJobTypeNotFound() throws Exception {
171 String url = ConsumerConsts.API_ROOT + "/eitypes/junk/eijobs";
172 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI type: junk");
176 void testGetEiJob() throws Exception {
177 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
178 putEiJob(EI_TYPE_ID, "jobId");
179 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
180 String rsp = restClient().get(url).block();
181 ConsumerEiJobInfo info = gson.fromJson(rsp, ConsumerEiJobInfo.class);
182 assertThat(info.owner).isEqualTo("owner");
186 void testGetEiJobNotFound() throws Exception {
187 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
188 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/junk";
189 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk");
193 void testGetEiJobStatus() throws Exception {
194 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
195 putEiJob(EI_TYPE_ID, "jobId");
196 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId/status";
197 String rsp = restClient().get(url).block();
198 assertThat(rsp).contains("ENABLED");
204 void testDeleteEiJob() throws Exception {
205 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
206 putEiJob(EI_TYPE_ID, "jobId");
207 assertThat(this.eiJobs.size()).isEqualTo(1);
208 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
209 restClient().delete(url).block();
210 assertThat(this.eiJobs.size()).isZero();
212 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
213 await().untilAsserted(() -> assertThat(simulatorResults.jobsStopped.size()).isEqualTo(1));
214 assertThat(simulatorResults.jobsStopped.get(0).id).isEqualTo("jobId");
218 void testDeleteEiJobNotFound() throws Exception {
219 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
220 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/junk";
221 testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND, "Could not find EI job: junk");
225 void testPutEiJob() throws Exception {
226 // Test that one producer accepting a job is enough
227 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
228 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
230 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
231 String body = gson.toJson(eiJobInfo());
232 ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
233 assertThat(this.eiJobs.size()).isEqualTo(1);
234 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
236 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
237 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
238 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
239 assertThat(request.id).isEqualTo("jobId");
241 assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(1);
243 resp = restClient().putForEntity(url, body).block();
244 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
245 EiJob job = this.eiJobs.getJob("jobId");
246 assertThat(job.owner()).isEqualTo("owner");
250 void putEiProducerWithOneType_rejecting() throws JsonMappingException, JsonProcessingException, ServiceException {
251 putEiProducerWithOneTypeRejecting("simulateProducerError", EI_TYPE_ID);
252 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
253 String body = gson.toJson(eiJobInfo());
254 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Job not accepted by any producers");
256 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
257 assertThat(simulatorResults.noOfRejectedCreate).isEqualTo(1);
261 void testPutEiJob_jsonSchemavalidationError() throws Exception {
262 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
264 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
265 // The element with name "property1" is mandatory in the schema
266 ConsumerEiJobInfo jobInfo =
267 new ConsumerEiJobInfo(jsonObject("{ \"XXstring\" : \"value\" }"), "owner", "targetUri");
268 String body = gson.toJson(jobInfo);
270 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT, "Json validation failure");
274 void testGetEiProducerTypes() throws Exception {
275 final String EI_TYPE_ID_2 = EI_TYPE_ID + "_2";
276 putEiProducerWithOneType("producer1", EI_TYPE_ID);
277 putEiJob(EI_TYPE_ID, "jobId");
278 putEiProducerWithOneType("producer2", EI_TYPE_ID_2);
279 putEiJob(EI_TYPE_ID_2, "jobId2");
280 String url = ProducerConsts.API_ROOT + "/eitypes";
282 ResponseEntity<String> resp = restClient().getForEntity(url).block();
283 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
284 assertThat(resp.getBody()).contains(EI_TYPE_ID);
285 assertThat(resp.getBody()).contains(EI_TYPE_ID_2);
289 void testReplacingEiProducerTypes() throws Exception {
290 final String REPLACED_TYPE_ID = "replaced";
291 putEiProducerWithOneType(EI_PRODUCER_ID, REPLACED_TYPE_ID);
292 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
294 String url = ProducerConsts.API_ROOT + "/eitypes";
296 ResponseEntity<String> resp = restClient().getForEntity(url).block();
297 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
298 assertThat(resp.getBody()).contains(EI_TYPE_ID);
299 assertThat(resp.getBody()).doesNotContain(REPLACED_TYPE_ID);
303 void testChangingEiTypeGetRejected() throws Exception {
304 putEiProducerWithOneType("producer1", "typeId1");
305 putEiProducerWithOneType("producer2", "typeId2");
306 putEiJob("typeId1", "jobId");
308 String url = ConsumerConsts.API_ROOT + "/eitypes/typeId2/eijobs/jobId";
309 String body = gson.toJson(eiJobInfo());
310 testErrorCode(restClient().put(url, body), HttpStatus.CONFLICT,
311 "Not allowed to change type for existing EI job");
315 void testPutEiProducer() throws Exception {
316 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
317 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
319 ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
320 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.CREATED);
322 assertThat(this.eiTypes.size()).isEqualTo(1);
323 EiType type = this.eiTypes.getType(EI_TYPE_ID);
324 assertThat(type.getProducerIds()).contains("eiProducerId");
325 assertThat(this.eiProducers.size()).isEqualTo(1);
326 assertThat(this.eiProducers.get("eiProducerId").eiTypes().iterator().next().getId()).isEqualTo(EI_TYPE_ID);
328 resp = restClient().putForEntity(url, body).block();
329 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
331 resp = restClient().getForEntity(url).block();
332 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
333 assertThat(resp.getBody()).isEqualTo(body);
337 void testPutEiProducerExistingJob() throws Exception {
338 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
339 putEiJob(EI_TYPE_ID, "jobId");
340 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
341 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
342 restClient().putForEntity(url, body).block();
344 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
345 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(2));
346 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
347 assertThat(request.id).isEqualTo("jobId");
351 void testPutProducerAndEiJob() throws Exception {
352 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
353 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
354 restClient().putForEntity(url, body).block();
355 assertThat(this.eiTypes.size()).isEqualTo(1);
356 this.eiTypes.getType(EI_TYPE_ID);
358 url = ConsumerConsts.API_ROOT + "/eitypes/typeId/eijobs/jobId";
359 body = gson.toJson(eiJobInfo());
360 restClient().putForEntity(url, body).block();
362 ProducerSimulatorController.TestResults simulatorResults = this.producerSimulator.getTestResults();
363 await().untilAsserted(() -> assertThat(simulatorResults.jobsStarted.size()).isEqualTo(1));
364 ProducerJobInfo request = simulatorResults.jobsStarted.get(0);
365 assertThat(request.id).isEqualTo("jobId");
369 void testGetEiJobsForProducer() throws JsonMappingException, JsonProcessingException, ServiceException {
370 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
371 putEiJob(EI_TYPE_ID, "jobId1");
372 putEiJob(EI_TYPE_ID, "jobId2");
375 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
376 String body = gson.toJson(producerEiRegistratioInfo(EI_TYPE_ID));
377 restClient().putForEntity(url, body).block();
379 url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId/eijobs";
380 ResponseEntity<String> resp = restClient().getForEntity(url).block();
381 assertThat(resp.getStatusCode()).isEqualTo(HttpStatus.OK);
383 ProducerJobInfo[] parsedResp = gson.fromJson(resp.getBody(), ProducerJobInfo[].class);
384 assertThat(parsedResp[0].typeId).isEqualTo(EI_TYPE_ID);
385 assertThat(parsedResp[1].typeId).isEqualTo(EI_TYPE_ID);
389 void testDeleteEiProducer() throws Exception {
390 putEiProducerWithOneType("eiProducerId", EI_TYPE_ID);
391 putEiProducerWithOneType("eiProducerId2", EI_TYPE_ID);
393 assertThat(this.eiProducers.size()).isEqualTo(2);
394 EiType type = this.eiTypes.getType(EI_TYPE_ID);
395 assertThat(type.getProducerIds()).contains("eiProducerId");
396 assertThat(type.getProducerIds()).contains("eiProducerId2");
397 putEiJob(EI_TYPE_ID, "jobId");
398 assertThat(this.eiJobs.size()).isEqualTo(1);
400 String url = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId";
401 restClient().deleteForEntity(url).block();
402 assertThat(this.eiProducers.size()).isEqualTo(1);
403 assertThat(this.eiTypes.getType(EI_TYPE_ID).getProducerIds()).doesNotContain("eiProducerId");
404 assertThat(this.eiJobs.size()).isEqualTo(1);
406 String url2 = ProducerConsts.API_ROOT + "/eiproducers/eiProducerId2";
407 restClient().deleteForEntity(url2).block();
408 assertThat(this.eiProducers.size()).isZero();
409 assertThat(this.eiTypes.size()).isZero();
410 assertThat(this.eiJobs.size()).isZero();
414 void testGetProducerEiType() throws JsonMappingException, JsonProcessingException, ServiceException {
415 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
416 String url = ProducerConsts.API_ROOT + "/eitypes/" + EI_TYPE_ID;
417 ResponseEntity<String> resp = restClient().getForEntity(url).block();
418 assertThat(resp.getBody()).contains(EI_PRODUCER_ID);
422 void testGetProducerIdentifiers() throws JsonMappingException, JsonProcessingException, ServiceException {
423 putEiProducerWithOneType(EI_PRODUCER_ID, EI_TYPE_ID);
424 String url = ProducerConsts.API_ROOT + "/eiproducers";
425 ResponseEntity<String> resp = restClient().getForEntity(url).block();
426 assertThat(resp.getBody()).contains(EI_PRODUCER_ID);
429 ProducerEiTypeRegistrationInfo producerEiTypeRegistrationInfo(String typeId)
430 throws JsonMappingException, JsonProcessingException {
431 return new ProducerEiTypeRegistrationInfo(jsonSchemaObject(), typeId);
434 ProducerRegistrationInfo producerEiRegistratioInfoRejecting(String typeId)
435 throws JsonMappingException, JsonProcessingException {
436 Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
437 types.add(producerEiTypeRegistrationInfo(typeId));
438 return new ProducerRegistrationInfo(types, baseUrl() + ProducerSimulatorController.JOB_CREATED_ERROR_URL,
439 baseUrl() + ProducerSimulatorController.JOB_DELETED_ERROR_URL);
442 ProducerRegistrationInfo producerEiRegistratioInfo(String typeId)
443 throws JsonMappingException, JsonProcessingException {
444 Collection<ProducerEiTypeRegistrationInfo> types = new ArrayList<>();
445 types.add(producerEiTypeRegistrationInfo(typeId));
446 return new ProducerRegistrationInfo(types, baseUrl() + ProducerSimulatorController.JOB_CREATED_URL,
447 baseUrl() + ProducerSimulatorController.JOB_DELETED_URL);
450 ConsumerEiJobInfo eiJobInfo() throws JsonMappingException, JsonProcessingException {
451 return new ConsumerEiJobInfo(jsonObject(), "owner", "targetUri");
454 Object jsonObject(String json) {
456 return JsonParser.parseString(json).getAsJsonObject();
457 } catch (Exception e) {
458 throw new NullPointerException(e.toString());
462 Object jsonSchemaObject() {
463 // a json schema with one mandatory property named "string"
464 String schemaStr = "{" //
465 + "\"$schema\": \"http://json-schema.org/draft-04/schema#\"," //
466 + "\"type\": \"object\"," //
467 + "\"properties\": {" //
468 + EI_JOB_PROPERTY + " : {" //
469 + " \"type\": \"string\"" //
472 + "\"required\": [" //
476 return jsonObject(schemaStr);
479 Object jsonObject() {
480 return jsonObject("{ " + EI_JOB_PROPERTY + " : \"value\" }");
483 private EiJob putEiJob(String eiTypeId, String jobId)
484 throws JsonMappingException, JsonProcessingException, ServiceException {
486 String url = ConsumerConsts.API_ROOT + "/eitypes/" + eiTypeId + "/eijobs/" + jobId;
487 String body = gson.toJson(eiJobInfo());
488 restClient().putForEntity(url, body).block();
490 return this.eiJobs.getJob(jobId);
493 private EiType putEiProducerWithOneTypeRejecting(String producerId, String eiTypeId)
494 throws JsonMappingException, JsonProcessingException, ServiceException {
495 String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
496 String body = gson.toJson(producerEiRegistratioInfoRejecting(eiTypeId));
498 restClient().putForEntity(url, body).block();
499 return this.eiTypes.getType(eiTypeId);
502 private EiType putEiProducerWithOneType(String producerId, String eiTypeId)
503 throws JsonMappingException, JsonProcessingException, ServiceException {
504 String url = ProducerConsts.API_ROOT + "/eiproducers/" + producerId;
505 String body = gson.toJson(producerEiRegistratioInfo(eiTypeId));
507 restClient().putForEntity(url, body).block();
508 return this.eiTypes.getType(eiTypeId);
511 private String baseUrl() {
512 return "https://localhost:" + this.port;
515 private AsyncRestClient restClient(boolean useTrustValidation) {
516 WebClientConfig config = this.applicationConfig.getWebClientConfig();
517 config = ImmutableWebClientConfig.builder() //
518 .keyStoreType(config.keyStoreType()) //
519 .keyStorePassword(config.keyStorePassword()) //
520 .keyStore(config.keyStore()) //
521 .keyPassword(config.keyPassword()) //
522 .isTrustStoreUsed(useTrustValidation) //
523 .trustStore(config.trustStore()) //
524 .trustStorePassword(config.trustStorePassword()) //
527 return new AsyncRestClient(baseUrl(), config);
530 private AsyncRestClient restClient() {
531 return restClient(false);
534 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
535 testErrorCode(request, expStatus, responseContains, true);
538 private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains,
539 boolean expectApplicationProblemJsonMediaType) {
540 StepVerifier.create(request) //
541 .expectSubscription() //
543 t -> checkWebClientError(t, expStatus, responseContains, expectApplicationProblemJsonMediaType)) //
547 private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains,
548 boolean expectApplicationProblemJsonMediaType) {
549 assertTrue(throwable instanceof WebClientResponseException);
550 WebClientResponseException responseException = (WebClientResponseException) throwable;
551 assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
552 assertThat(responseException.getResponseBodyAsString()).contains(responseContains);
553 if (expectApplicationProblemJsonMediaType) {
554 assertThat(responseException.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_PROBLEM_JSON);