<artifactId>cps-ncmp-service</artifactId>
<properties>
- <minimum-coverage>0.96</minimum-coverage>
+ <minimum-coverage>0.97</minimum-coverage>
</properties>
<dependencies>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
.queryParameter("destination", destination)
.createUrlTemplateParameters(dmiServiceName,
dmiServiceAuthenticationProperties.getDmiBasePath());
- return dmiRestClient.getDataJobResult(urlTemplateParameters, authorization).block();
+ return dmiRestClient.asynchronousDmiDataRequest(urlTemplateParameters, authorization).block();
}
}
final UrlTemplateParameters urlTemplateParameters = buildUrlParameters(dmiServiceName,
dataProducerId,
dataProducerJobId);
- return dmiRestClient.getDataJobStatus(urlTemplateParameters, authorization).block();
+ return dmiRestClient.asynchronousDmiDataRequest(urlTemplateParameters, authorization).block();
}
private UrlTemplateParameters buildUrlParameters(final String dmiServiceName,
import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA;
import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR;
+import static org.onap.cps.ncmp.api.data.models.OperationType.READ;
+import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.REQUEST_TIMEOUT;
import java.util.Locale;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
+import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.data.models.OperationType;
import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException;
import org.onap.cps.ncmp.impl.models.RequiredDmiService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
-import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
final String requestBodyAsJsonString,
final OperationType operationType,
final String authorization) {
- final Mono<ResponseEntity<Object>> responseEntityMono =
- asynchronousPostOperation(requiredDmiService,
- urlTemplateParameters,
- requestBodyAsJsonString,
- operationType,
- authorization);
- return responseEntityMono.block();
+ return asynchronousPostOperation(requiredDmiService,
+ urlTemplateParameters,
+ requestBodyAsJsonString,
+ operationType,
+ authorization).block();
}
/**
* @param authorization The authorization token to be added to the request headers.
* @return A Mono emitting the response entity containing the server's response.
*/
- public Mono<ResponseEntity<Object>> asynchronousPostOperation(final RequiredDmiService
- requiredDmiService,
- final UrlTemplateParameters
- urlTemplateParameters,
- final String requestBodyAsJsonString,
- final OperationType operationType,
- final String authorization) {
+ public Mono<ResponseEntity<Object>> asynchronousPostOperation(final RequiredDmiService requiredDmiService,
+ final UrlTemplateParameters urlTemplateParameters,
+ final String requestBodyAsJsonString,
+ final OperationType operationType,
+ final String authorization) {
final WebClient webClient = getWebClient(requiredDmiService);
return webClient.post()
.uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
* @throws DmiClientRequestException If there is an error during the DMI request.
*/
public ResponseEntity<Object> synchronousGetOperation(final RequiredDmiService requiredDmiService,
- final UrlTemplateParameters
- urlTemplateParameters,
- final OperationType operationType) {
+ final UrlTemplateParameters urlTemplateParameters,
+ final OperationType operationType) {
return getWebClient(requiredDmiService)
.get()
.uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
.headers(httpHeaders -> configureHttpHeaders(httpHeaders, NO_AUTHORIZATION))
.retrieve()
.toEntity(Object.class)
- .onErrorMap(throwable -> handleDmiClientException(throwable, operationType.getOperationName()))
+ .onErrorMap(throwable ->
+ handleDmiClientException(throwable, operationType.getOperationName()))
.block();
}
* @throws DmiClientRequestException If there is an error during the DMI request.
*/
public ResponseEntity<Object> synchronousPutOperation(final RequiredDmiService requiredDmiService,
- final UrlTemplateParameters
- urlTemplateParameters,
- final OperationType operationType) {
+ final UrlTemplateParameters urlTemplateParameters,
+ final OperationType operationType) {
return getWebClient(requiredDmiService)
.get()
.uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
}
/**
- * Retrieves the status of a data job from the DMI service.
+ * Retrieves the result of a data get request from the DMI service asynchronously.
*
- * @param urlTemplateParameters The URL template parameters for the DMI data job status endpoint.
+ * @param urlTemplateParameters The URL template parameters for the DMI data endpoint.
* @param authorization The authorization token to be added to the request headers.
- * @return A Mono emitting the status of the data job in JSON format.
- * @throws DmiClientRequestException If there is an error during the DMI request.
+ * @return A Mono emitting the result of the request as a String.
*/
- public Mono<String> getDataJobStatus(final UrlTemplateParameters urlTemplateParameters,
- final String authorization) {
+ public Mono<String> asynchronousDmiDataRequest(final UrlTemplateParameters urlTemplateParameters,
+ final String authorization) {
return dataServicesWebClient.get()
.uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
.headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
.retrieve()
.bodyToMono(String.class)
- .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.READ.getOperationName()));
- }
-
- /**
- * Retrieves the result of a data job from the DMI service.
- *
- * @param urlTemplateParameters The URL template parameters for the DMI data job status endpoint.
- * @param authorization The authorization token to be added to the request headers.
- * @return A Mono emitting the result of the data job as a String.
- * @throws DmiClientRequestException If there is an error during the DMI request.
- */
- public Mono<String> getDataJobResult(final UrlTemplateParameters urlTemplateParameters,
- final String authorization) {
- return dataServicesWebClient.get()
- .uri(urlTemplateParameters.urlTemplate(), urlTemplateParameters.urlVariables())
- .headers(httpHeaders -> configureHttpHeaders(httpHeaders, authorization))
- .retrieve().bodyToMono(String.class)
- .onErrorMap(throwable -> handleDmiClientException(throwable, OperationType.READ.getOperationName()));
+ .onErrorMap(throwable -> handleDmiClientException(throwable, READ.getOperationName()));
}
/**
}
private WebClient getWebClient(final RequiredDmiService requiredDmiService) {
- return requiredDmiService.equals(RequiredDmiService.DATA) ? dataServicesWebClient : modelServicesWebClient;
+ return DATA.equals(requiredDmiService) ? dataServicesWebClient : modelServicesWebClient;
}
private void configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) {
private DmiClientRequestException handleDmiClientException(final Throwable throwable, final String operationType) {
if (throwable instanceof WebClientResponseException webClientResponseException) {
- if (webClientResponseException.getStatusCode().isSameCodeAs(REQUEST_TIMEOUT)) {
- throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
- webClientResponseException.getMessage(),
- jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()),
- DMI_SERVICE_NOT_RESPONDING);
- }
- throw new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
+ final NcmpResponseStatus ncmpResponseStatus = webClientResponseException.getStatusCode()
+ .isSameCodeAs(REQUEST_TIMEOUT) ? DMI_SERVICE_NOT_RESPONDING : UNABLE_TO_READ_RESOURCE_DATA;
+ return new DmiClientRequestException(webClientResponseException.getStatusCode().value(),
webClientResponseException.getMessage(),
jsonObjectMapper.asJsonString(webClientResponseException.getResponseBodyAsString()),
- UNABLE_TO_READ_RESOURCE_DATA);
-
+ ncmpResponseStatus);
}
final String exceptionMessage = "Unable to " + operationType + " resource data.";
- if (throwable instanceof WebClientRequestException webClientRequestException) {
- throw new DmiClientRequestException(HttpStatus.SERVICE_UNAVAILABLE.value(),
- webClientRequestException.getMessage(),
+ if (throwable instanceof WebClientRequestException) {
+ return new DmiClientRequestException(HttpStatus.SERVICE_UNAVAILABLE.value(), throwable.getMessage(),
exceptionMessage, DMI_SERVICE_NOT_RESPONDING);
}
- if (throwable instanceof HttpServerErrorException httpServerErrorException) {
- throw new DmiClientRequestException(httpServerErrorException.getStatusCode().value(), exceptionMessage,
- httpServerErrorException.getResponseBodyAsString(), DMI_SERVICE_NOT_RESPONDING);
- }
- throw new DmiClientRequestException(INTERNAL_SERVER_ERROR.value(), exceptionMessage, throwable.getMessage(),
+ return new DmiClientRequestException(INTERNAL_SERVER_ERROR.value(), exceptionMessage, throwable.getMessage(),
UNKNOWN_ERROR);
}
+
}
def destination = 'some-destination'
def urlParams = new UrlTemplateParameters('some-dmi-service/dmi/v1/cmwriteJob/dataProducer/{dataProducerId}/dataProducerJob/{dataProducerJobId}/result?destination={destination}', ['dataProducerJobId':'some-data-producer-job-id', 'dataProducerId':'some-data-producer-id', 'destination': 'some-destination'])
and: 'the rest client returns the result for the given parameters'
- mockDmiRestClient.getDataJobResult(urlParams, authorization) >> Mono.just('some result')
+ mockDmiRestClient.asynchronousDmiDataRequest(urlParams, authorization) >> Mono.just('some result')
when: 'the job status is queried'
def result = objectUnderTest.getDataJobResult(authorization, dmiServiceName,dataProducerId, dataProducerJobId, destination)
then: 'the result from the rest client is returned'
def authorization = 'my authorization header'
def urlParams = new UrlTemplateParameters('some-dmi-service/dmi/v1/cmwriteJob/dataProducer/{dataProducerId}/dataProducerJob/{dataProducerJobId}/status', ['dataProducerId':'some-data-producer-id', 'dataProducerJobId':'some-data-producer-job-id'])
and: 'the rest client returns a status for the given parameters'
- mockDmiRestClient.getDataJobStatus(urlParams, authorization) >> Mono.just('some status')
+ mockDmiRestClient.asynchronousDmiDataRequest(urlParams, authorization) >> Mono.just('some status')
when: 'the job status is queried'
def status = objectUnderTest.getDataJobStatus(authorization, dmiServiceName, dataProducerId, dataProducerJobId)
then: 'the status from the rest client is returned'
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.dmi
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import okhttp3.mockwebserver.MockResponse
+import okhttp3.mockwebserver.MockWebServer
+import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
+import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
+import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.http.HttpStatus
+import org.springframework.web.reactive.function.client.WebClient
+import org.springframework.web.util.InvalidUrlException
+import spock.lang.Specification
+
+import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE
+import static org.onap.cps.ncmp.api.data.models.OperationType.READ
+import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE
+import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA
+import static org.onap.cps.ncmp.impl.models.RequiredDmiService.MODEL
+
+class DmiRestClientIntegrationSpec extends Specification {
+
+ def mockWebServer = new MockWebServer()
+ def baseUrl = mockWebServer.url('/')
+ def webClientForMockServer = WebClient.builder().baseUrl(baseUrl.toString()).build()
+
+ def urlTemplateParameters = new UrlTemplateParameters('/myPath', [someParam: 'value'])
+ def mockDmiServiceAuthenticationProperties = Mock(DmiServiceAuthenticationProperties)
+
+ JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ def objectUnderTest = new DmiRestClient(mockDmiServiceAuthenticationProperties, jsonObjectMapper, webClientForMockServer, webClientForMockServer, webClientForMockServer)
+
+ def cleanup() throws IOException {
+ mockWebServer.shutdown()
+ }
+
+ def 'Synchronous DMI #method request.'() {
+ given: 'Web Server wil return OK response'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value))
+ when: 'synchronous #method request is made'
+ def result
+ switch(method) {
+ case 'get':
+ result = objectUnderTest.synchronousGetOperation(DATA, urlTemplateParameters, READ)
+ break
+ case 'post':
+ result = objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'body', CREATE, '')
+ break
+ case 'put':
+ result = objectUnderTest.synchronousPutOperation(DATA, urlTemplateParameters, UPDATE)
+ break
+ case 'delete':
+ result = objectUnderTest.synchronousDeleteOperation(DATA, urlTemplateParameters)
+ }
+ then: 'the result has the same status code of 200'
+ assert result.statusCode.value() == 200
+ where: 'the following http methods are used'
+ method << ['get', 'post', 'put', 'delete']
+ }
+
+ def 'Synchronous DMI #method request with invalid JSON.'() {
+ given: 'Web Server wil return OK response'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value)
+ .setBody('invalid-json:!!')
+ .addHeader('Content-Type', 'application/json'))
+ when: 'synchronous #method request is attempted (on Model service this time for coverage on service selector)'
+ switch(method) {
+ case 'get':
+ objectUnderTest.synchronousGetOperation(MODEL, urlTemplateParameters, READ)
+ break;
+ case 'post':
+ objectUnderTest.synchronousPostOperation(MODEL, urlTemplateParameters, 'body', READ, 'some authorization')
+ break
+ case 'put':
+ objectUnderTest.synchronousPutOperation(MODEL, urlTemplateParameters, UPDATE)
+ break
+ case 'delete':
+ objectUnderTest.synchronousDeleteOperation(MODEL, urlTemplateParameters)
+ }
+ then: 'a dmi client request exception is thrown with the correct error codes'
+ def thrown = thrown(DmiClientRequestException)
+ assert thrown.getHttpStatusCode() == 500
+ assert thrown.ncmpResponseStatus.code == '108'
+ where: 'the following http methods are used'
+ method << ['get','post','put','delete']
+ }
+
+ def 'DMI Request with non-responding server.'() {
+ given: 'the web server is shut down'
+ mockWebServer.shutdown()
+ when: 'a synchronous read request is attempted'
+ objectUnderTest.synchronousGetOperation(DATA, urlTemplateParameters, READ)
+ then: 'a dmi client request exception is thrown with status code of 503 Service Unavailable'
+ def thrown = thrown(DmiClientRequestException)
+ assert thrown.getHttpStatusCode() == 503
+ }
+
+ def 'DMI Request with #scenario.'() {
+ given: 'the mock server or exception setup'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(responseCode.value))
+ when: 'a synchronous read request is attempted'
+ objectUnderTest.synchronousGetOperation(DATA, urlTemplateParameters, READ)
+ then: 'a DMI client request exception is thrown with the right status'
+ def thrown = thrown(DmiClientRequestException)
+ assert thrown.httpStatusCode == expectedStatus
+ where: 'the following HTTP Errors are applied'
+ scenario | responseCode || expectedStatus
+ 'Client error (418)' | HttpStatus.I_AM_A_TEAPOT || 418
+ 'Timeout (408)' | HttpStatus.REQUEST_TIMEOUT || 408
+ 'Server error (503)' | HttpStatus.SERVICE_UNAVAILABLE || 503
+ }
+
+ def 'DMI Request with unexpected runtime exception.'() {
+ given: 'Mock a bad URL that causes IllegalArgumentException before HTTP call'
+ def badUrlParameters = new UrlTemplateParameters(':://bad url', [someParam: 'value'])
+ when: 'a synchronous request is attempted'
+ objectUnderTest.synchronousGetOperation(DATA, badUrlParameters, READ)
+ then: 'a invalid url exception is thrown (no mapping)'
+ thrown(InvalidUrlException)
+ }
+
+ def 'DMI health status check with #scenario.'() {
+ given: 'Web Server will return OK response with status TEST'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value)
+ .setBody(jsonBody)
+ .addHeader('Content-Type', 'application/json'))
+ when: 'DMI health status is checked'
+ def result = objectUnderTest.getDmiHealthStatus(urlTemplateParameters).block()
+ then: 'result is as expected'
+ result == expectedResult
+ where: 'following json data is used'
+ scenario | jsonBody || expectedResult
+ 'Valid Json' | '{"status":"TEST"}' || 'TEST'
+ 'Invalid Json' | 'invalid-json:!!' || ''
+ }
+
+ def 'Asynchronous DMI data request.'() {
+ given: 'web Server will return OK response with status TEST'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.OK.value).setBody('TEST'))
+ when: 'asynchronous DMI data request is made'
+ def result = objectUnderTest.asynchronousDmiDataRequest(urlTemplateParameters, 'some authorization').block()
+ then: 'result is TEST'
+ assert result == 'TEST'
+ }
+
+ def 'Asynchronous DMI Data Request with Http Error'() {
+ given: 'web Server will return OK response with status TEST'
+ mockWebServer.enqueue(new MockResponse().setResponseCode(HttpStatus.I_AM_A_TEAPOT.value))
+ when: 'asynchronous DMI data request is attempted'
+ objectUnderTest.asynchronousDmiDataRequest(urlTemplateParameters, 'some authorization').block()
+ then: 'a DMI client request exception is thrown with the same status code 418'
+ def thrown = thrown(DmiClientRequestException)
+ assert thrown.getHttpStatusCode() == 418
+ }
+
+}
package org.onap.cps.ncmp.impl.dmi
-import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.databind.node.ObjectNode
-import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException
-import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters
-import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.utils.JsonObjectMapper
import org.springframework.http.HttpHeaders
-import org.springframework.http.HttpStatus
-import org.springframework.http.HttpStatusCode
-import org.springframework.http.ResponseEntity
-import org.springframework.web.client.HttpServerErrorException
-import org.springframework.web.reactive.function.client.WebClient
-import org.springframework.web.reactive.function.client.WebClientRequestException
-import org.springframework.web.reactive.function.client.WebClientResponseException
-import reactor.core.publisher.Mono
import spock.lang.Specification
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.DMI_SERVICE_NOT_RESPONDING
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNABLE_TO_READ_RESOURCE_DATA
-import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR
-import static org.onap.cps.ncmp.api.data.models.OperationType.READ
-import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA
-import static org.onap.cps.ncmp.impl.models.RequiredDmiService.MODEL
-
class DmiRestClientSpec extends Specification {
- static final NO_AUTH_HEADER = null
- static final BASIC_AUTH_HEADER = 'Basic c29tZSB1c2VyOnNvbWUgcGFzc3dvcmQ='
- static final BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
- static final urlTemplateParameters = new UrlTemplateParameters('/{pathParam1}/{pathParam2}', ['pathParam1': 'my', 'pathParam2': 'url'])
-
- def mockDataServicesWebClient = Mock(WebClient)
- def mockModelServicesWebClient = Mock(WebClient)
- def mockHealthChecksWebClient = Mock(WebClient)
-
- def mockRequestBodyUriSpec = Mock(WebClient.RequestBodyUriSpec)
- def mockResponseSpec = Mock(WebClient.ResponseSpec)
+ static NO_AUTH_HEADER = null
+ static BASIC_AUTH_HEADER = 'Basic c29tZSB1c2VyOnNvbWUgcGFzc3dvcmQ='
+ static BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
def mockDmiServiceAuthenticationProperties = Mock(DmiServiceAuthenticationProperties)
JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
- def responseFromDmiService = new ResponseEntity<>('Response from DMI service', HttpStatus.I_AM_A_TEAPOT)
-
- DmiRestClient objectUnderTest = new DmiRestClient(mockDmiServiceAuthenticationProperties, jsonObjectMapper, mockDataServicesWebClient, mockModelServicesWebClient, mockHealthChecksWebClient)
-
- def setup() {
- mockRequestBodyUriSpec.uri(*_) >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.headers(_) >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.body(_) >> mockRequestBodyUriSpec
- mockRequestBodyUriSpec.retrieve() >> mockResponseSpec
- }
- def 'DMI POST Operation with JSON for DMI Data Service.'() {
- given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.post() >> mockRequestBodyUriSpec
- mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
- when: 'POST operation is invoked for Data Service'
- def result = objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
- then: 'the output of the method is equal to the output from dmi service'
- assert result.equals(responseFromDmiService)
- }
-
- def 'DMI POST Operation with JSON for DMI Model Service.'() {
- given: 'the Model web client returns a valid response entity for the expected parameters'
- mockModelServicesWebClient.post() >> mockRequestBodyUriSpec
- mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
- when: 'POST operation is invoked for Model Service'
- def result = objectUnderTest.synchronousPostOperation(MODEL, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
- then: 'the output of the method is equal to the output from the dmi service'
- assert result.equals(responseFromDmiService)
- }
-
- def 'Synchronous DMI POST operation with #scenario.'() {
- given: 'the web client unable to return response entity but error'
- mockDataServicesWebClient.post() >> mockRequestBodyUriSpec
- mockResponseSpec.toEntity(Object.class) >> Mono.error(exception)
- when: 'POST operation is invoked'
- objectUnderTest.synchronousPostOperation(DATA, urlTemplateParameters, 'some json', READ, NO_AUTH_HEADER)
- then: 'a http client exception is thrown'
- def thrown = thrown(DmiClientRequestException)
- and: 'the exception has the relevant details from the error response'
- assert thrown.ncmpResponseStatus == expectedNcmpResponseStatusCode
- assert thrown.httpStatusCode == httpStatusCode
- where: 'the following errors occur'
- scenario | httpStatusCode | exception || expectedNcmpResponseStatusCode
- 'dmi service unavailable' | 503 | new WebClientRequestException(new RuntimeException('some-error'), null, null, new HttpHeaders()) || DMI_SERVICE_NOT_RESPONDING
- 'dmi request timeout' | 408 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || DMI_SERVICE_NOT_RESPONDING
- 'dmi server error' | 500 | new WebClientResponseException('message', httpStatusCode, 'statusText', null, null, null) || UNABLE_TO_READ_RESOURCE_DATA
- 'dmi service unavailable' | 503 | new HttpServerErrorException(HttpStatusCode.valueOf(503)) || DMI_SERVICE_NOT_RESPONDING
- 'unknown error' | 500 | new Throwable('message') || UNKNOWN_ERROR
- }
-
- def 'Synchronous DMI GET Operation.'() {
- given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.toEntity(_) >> Mono.just(responseFromDmiService)
- when: 'GET operation is invoked for Data Service'
- def result = objectUnderTest.synchronousGetOperation(DATA, urlTemplateParameters, READ)
- then: 'the output of the method is equal to the output from the DMI service'
- assert result.equals(responseFromDmiService)
- }
-
- def 'Dmi trust level is determined by spring boot health status.'() {
- given: 'a health check response'
- def dmiPluginHealthCheckResponseJsonData = TestUtils.getResourceFileContent('dmiPluginHealthCheckResponse.json')
- def jsonNode = jsonObjectMapper.convertJsonString(dmiPluginHealthCheckResponseJsonData, JsonNode.class)
- ((ObjectNode) jsonNode).put('status', 'my status')
- mockHealthChecksWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.bodyToMono(JsonNode.class) >> Mono.just(jsonNode)
- when: 'get trust level of the dmi plugin'
- def urlTemplateParameters = new UrlTemplateParameters('some url', [:])
- def result = objectUnderTest.getDmiHealthStatus(urlTemplateParameters).block()
- then: 'the status value from the json is returned'
- assert result == 'my status'
- }
-
- def 'Failing to get dmi plugin health status #scenario.'() {
- given: 'web client instance with #scenario'
- mockHealthChecksWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.bodyToMono(_) >> Mono.error(exceptionType)
- when: 'attempt to get health status of the dmi plugin'
- def urlTemplateParameters = new UrlTemplateParameters('some url', [:])
- def result = objectUnderTest.getDmiHealthStatus(urlTemplateParameters).block()
- then: 'result will be empty'
- assert result == ''
- where: 'the following responses are used'
- scenario | exceptionType
- 'dmi request timeout' | new WebClientResponseException('some-message', 408, 'some-text', null, null, null)
- 'dmi service unavailable' | new HttpServerErrorException(HttpStatus.SERVICE_UNAVAILABLE)
- }
+ DmiRestClient objectUnderTest = new DmiRestClient(mockDmiServiceAuthenticationProperties, jsonObjectMapper, null, null, null)
def 'DMI auth header #scenario.'() {
when: 'Specific dmi properties are provided'
'DMI basic auth disabled, with NCMP bearer token' | false | BEARER_AUTH_HEADER || BEARER_AUTH_HEADER
'DMI basic auth disabled, with NCMP basic auth' | false | BASIC_AUTH_HEADER || NO_AUTH_HEADER
}
-
- def 'DMI Data Job Status request for DMI Data Service.'() {
- given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.bodyToMono(String.class) >> Mono.just(responseFromDmiService)
- when: 'Data job status is invoked for Data Service'
- def result = objectUnderTest.getDataJobStatus(urlTemplateParameters, NO_AUTH_HEADER).block()
- then: 'the response equals to response from the DMI service'
- assert result.equals(responseFromDmiService)
- }
-
- def 'Get data job result from DMI.'() {
- given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.get() >> mockRequestBodyUriSpec
- mockResponseSpec.bodyToMono(String.class) >> Mono.just(responseFromDmiService)
- when: 'GET operation is invoked for Data Service'
- def result = objectUnderTest.getDataJobResult(urlTemplateParameters, NO_AUTH_HEADER).block()
- then: 'the response has some value'
- assert result.equals(responseFromDmiService)
- }
-
- def 'DMI DELETE Operation for DMI Data Service.'() {
- given: 'the Data web client returns a valid response entity for the expected parameters'
- mockDataServicesWebClient.delete() >> mockRequestBodyUriSpec
- mockResponseSpec.toEntity(Object.class) >> Mono.just(responseFromDmiService)
- when: 'DELETE operation is invoked for Data Service'
- def result = objectUnderTest.synchronousDeleteOperation(DATA, urlTemplateParameters)
- then: 'The response is the same as the response from the DMI service'
- assert result.equals(responseFromDmiService)
- }
}