The backend listens to port 8434 for https.
Port 8080 is still open for http
In this commit, the backend uses http://policy-agent-container:8081 towards the
policy agent.
Using https://policy-agent-container:8433 is tested.
Change-Id: I2c09d888a55ca156c33b12a83f27b7131478caf8
Issue-ID: NONRTRIC-195
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-
-<![CDATA[
+<!--<![CDATA[
========================LICENSE_START=================================
O-RAN-SC
%%
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-webflux</artifactId>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<artifactId>junit-platform-launcher</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>io.projectreactor</groupId>
+ <artifactId>reactor-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>mockwebserver</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
<plugins>
/**
* Gets version details for the specified class.
*
- * @param clazz
- * Class to get the version
+ * @param clazz Class to get the version
*
* @return the value of the MANIFEST.MF property Implementation-Version as
* written by maven when packaged in a jar; 'unknown' otherwise.
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 Nordix Foundation
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+package org.oransc.portal.nonrtric.controlpanel.config;
+
+import org.apache.catalina.connector.Connector;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class TomcatWebServerConfiguration {
+
+ @Bean
+ public ServletWebServerFactory servletContainer() {
+ TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
+ tomcat.addAdditionalTomcatConnectors(getHttpConnector());
+ return tomcat;
+ }
+
+ private static Connector getHttpConnector() {
+ Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
+ connector.setScheme("http");
+ connector.setPort(8080);
+ connector.setSecure(false);
+ return connector;
+ }
+
+}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
+
+import javax.net.ssl.SSLException;
import org.immutables.gson.Gson;
import org.immutables.value.Value;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyInstances;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyType;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyTypes;
+import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
-import org.springframework.web.client.RestTemplate;
@Component("PolicyAgentApi")
public class PolicyAgentApiImpl implements PolicyAgentApi {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- RestTemplate restTemplate;
+ private final AsyncRestClient webClient;
private static com.google.gson.Gson gson = new GsonBuilder() //
.serializeNulls() //
.create(); //
- private final String urlPrefix;
-
@Autowired
public PolicyAgentApiImpl(
@org.springframework.beans.factory.annotation.Value("${policycontroller.url.prefix}") final String urlPrefix) {
- this(urlPrefix, new RestTemplate());
+ this(new AsyncRestClient(urlPrefix));
logger.debug("ctor prefix '{}'", urlPrefix);
}
- public PolicyAgentApiImpl(String urlPrefix, RestTemplate restTemplate) {
- this.urlPrefix = urlPrefix;
- this.restTemplate = restTemplate;
- }
-
- private String baseUrl() {
- return urlPrefix;
- }
-
- @Value.Immutable
- @Gson.TypeAdapters
- interface PolicyTypeInfo {
-
- public String name();
-
- public String schema();
+ public PolicyAgentApiImpl(AsyncRestClient webClient) {
+ this.webClient = webClient;
}
@Override
public ResponseEntity<String> getAllPolicyTypes() {
try {
- String url = baseUrl() + "/policy_schemas";
- ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class);
+ final String url = "/policy_schemas";
+ ResponseEntity<String> rsp = webClient.getForEntity(url).block();
if (!rsp.getStatusCode().is2xxSuccessful()) {
return rsp;
}
@Override
public ResponseEntity<String> getPolicyInstancesForType(String type) {
- String url = baseUrl() + "/policies?type={type}";
- Map<String, ?> uriVariables = Map.of("type", type);
- ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class, uriVariables);
- if (!rsp.getStatusCode().is2xxSuccessful()) {
- return rsp;
- }
-
try {
+ String url = "/policies?type=" + type;
+ ResponseEntity<String> rsp = webClient.getForEntity(url).block();
+ if (!rsp.getStatusCode().is2xxSuccessful()) {
+ return rsp;
+ }
+
Type listType = new TypeToken<List<ImmutablePolicyInfo>>() {}.getType();
List<PolicyInfo> rspParsed = gson.fromJson(rsp.getBody(), listType);
PolicyInstances result = new PolicyInstances();
@Override
public ResponseEntity<Object> getPolicyInstance(String id) {
- String url = baseUrl() + "/policy?id={id}";
- Map<String, ?> uriVariables = Map.of("id", id);
-
- return this.restTemplate.getForEntity(url, Object.class, uriVariables);
+ try {
+ String url = "/policy?id=" + id;
+ ResponseEntity<String> rsp = webClient.getForEntity(url).block();
+ JsonObject obj = JsonParser.parseString(rsp.getBody()).getAsJsonObject();
+ String str = obj.toString();
+ return new ResponseEntity<>(str, rsp.getStatusCode());
+ } catch (Exception e) {
+ ResponseEntity<String> rsp = handleException(e);
+ return new ResponseEntity<>(rsp.getBody(), rsp.getStatusCode());
+ }
}
@Override
public ResponseEntity<String> putPolicy(String policyTypeIdString, String policyInstanceId, Object json,
String ric) {
- String url = baseUrl() + "/policy?type={type}&id={id}&ric={ric}&service={service}";
- Map<String, ?> uriVariables = Map.of( //
- "type", policyTypeIdString, //
- "id", policyInstanceId, //
- "ric", ric, //
- "service", "controlpanel");
+ String url =
+ "/policy?type=" + policyTypeIdString + "&id=" + policyInstanceId + "&ric=" + ric + "&service=controlpanel";
try {
- this.restTemplate.put(url, createJsonHttpEntity(json), uriVariables);
+ String jsonStr = json.toString();
+ webClient.putForEntity(url, jsonStr).block();
return new ResponseEntity<>(HttpStatus.OK);
} catch (Exception e) {
return handleException(e);
@Override
public ResponseEntity<String> deletePolicy(String policyInstanceId) {
- String url = baseUrl() + "/policy?id={id}";
- Map<String, ?> uriVariables = Map.of("id", policyInstanceId);
+ String url = "/policy?id=" + policyInstanceId;
try {
- this.restTemplate.delete(url, uriVariables);
+ webClient.deleteForEntity(url).block();
return new ResponseEntity<>(HttpStatus.OK);
} catch (Exception e) {
return handleException(e);
}
-
}
@Value.Immutable
@Override
public ResponseEntity<String> getRicsSupportingType(String typeName) {
- String url = baseUrl() + "/rics?policyType={typeName}";
- Map<String, ?> uriVariables = Map.of("typeName", typeName);
- String rsp = this.restTemplate.getForObject(url, String.class, uriVariables);
-
try {
+ String url = "/rics?policyType=" + typeName;
+ ResponseEntity<String> rsp = webClient.getForEntity(url).block();
+
Type listType = new TypeToken<List<ImmutableRicInfo>>() {}.getType();
- List<RicInfo> rspParsed = gson.fromJson(rsp, listType);
+ List<RicInfo> rspParsed = gson.fromJson(rsp.getBody(), listType);
Collection<String> result = new ArrayList<>(rspParsed.size());
for (RicInfo ric : rspParsed) {
result.add(ric.ricName());
}
- return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK);
+ String json = gson.toJson(result);
+ return new ResponseEntity<>(json, HttpStatus.OK);
} catch (Exception e) {
return handleException(e);
}
}
- private HttpEntity<Object> createJsonHttpEntity(Object content) {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON);
- return new HttpEntity<>(content, headers);
- }
-
private ResponseEntity<String> handleException(Exception throwable) {
if (throwable instanceof HttpClientErrorException) {
HttpClientErrorException e = (HttpClientErrorException) throwable;
} else if (throwable instanceof HttpServerErrorException) {
HttpServerErrorException e = (HttpServerErrorException) throwable;
return new ResponseEntity<>(e.getResponseBodyAsString(), e.getStatusCode());
+ } else if (throwable instanceof SSLException) {
+ SSLException e = (SSLException) throwable;
+ return new ResponseEntity<>("Could not create WebClient " + e.getMessage(),
+ HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(throwable.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
-
}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 Nordix Foundation
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.portal.nonrtric.controlpanel.util;
+
+import io.netty.channel.ChannelOption;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.handler.timeout.ReadTimeoutHandler;
+import io.netty.handler.timeout.WriteTimeoutHandler;
+
+import java.lang.invoke.MethodHandles;
+
+import javax.net.ssl.SSLException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.reactive.ReactorClientHttpConnector;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import reactor.core.publisher.Mono;
+import reactor.netty.http.client.HttpClient;
+import reactor.netty.tcp.TcpClient;
+
+/**
+ * Generic reactive REST client.
+ */
+public class AsyncRestClient {
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private WebClient webClient = null;
+ private final String baseUrl;
+
+ public AsyncRestClient(String baseUrl) {
+ this.baseUrl = baseUrl;
+ }
+
+ public Mono<ResponseEntity<String>> putForEntity(String uri, String body) {
+ logger.debug("PUT uri = '{}{}''", baseUrl, uri);
+ return getWebClient() //
+ .flatMap(client -> {
+ RequestHeadersSpec<?> request = client.put() //
+ .uri(uri) //
+ .contentType(MediaType.APPLICATION_JSON) //
+ .bodyValue(body);
+ return retrieve(request);
+ });
+ }
+
+ public Mono<ResponseEntity<String>> putForEntity(String uri) {
+ logger.debug("PUT uri = '{}{}''", baseUrl, uri);
+ return getWebClient() //
+ .flatMap(client -> {
+ RequestHeadersSpec<?> request = client.put() //
+ .uri(uri);
+ return retrieve(request);
+ });
+ }
+
+ public Mono<String> put(String uri, String body) {
+ return putForEntity(uri, body) //
+ .flatMap(this::toBody);
+ }
+
+ public Mono<ResponseEntity<String>> getForEntity(String uri) {
+ logger.debug("GET uri = '{}{}''", baseUrl, uri);
+ return getWebClient() //
+ .flatMap(client -> {
+ RequestHeadersSpec<?> request = client.get().uri(uri);
+ return retrieve(request);
+ });
+ }
+
+ public Mono<String> get(String uri) {
+ return getForEntity(uri) //
+ .flatMap(this::toBody);
+ }
+
+ public Mono<ResponseEntity<String>> deleteForEntity(String uri) {
+ logger.debug("DELETE uri = '{}{}''", baseUrl, uri);
+ return getWebClient() //
+ .flatMap(client -> {
+ RequestHeadersSpec<?> request = client.delete().uri(uri);
+ return retrieve(request);
+ });
+ }
+
+ public Mono<String> delete(String uri) {
+ return deleteForEntity(uri) //
+ .flatMap(this::toBody);
+ }
+
+ private Mono<ResponseEntity<String>> retrieve(RequestHeadersSpec<?> request) {
+ return request.retrieve() //
+ .toEntity(String.class) //
+ .doOnError(this::onHttpError);
+ }
+
+ private void onHttpError(Throwable t) {
+ if (t instanceof WebClientResponseException) {
+ WebClientResponseException exception = (WebClientResponseException) t;
+ logger.debug("HTTP error status = '{}', body '{}'", exception.getStatusCode(),
+ exception.getResponseBodyAsString());
+ } else {
+ logger.debug("HTTP error: {}", t.getMessage());
+ }
+ }
+
+ private Mono<String> toBody(ResponseEntity<String> entity) {
+ if (entity.getBody() == null) {
+ return Mono.just("");
+ } else {
+ return Mono.just(entity.getBody());
+ }
+ }
+
+ private static SslContext createSslContext() throws SSLException {
+ return SslContextBuilder.forClient() //
+ .trustManager(InsecureTrustManagerFactory.INSTANCE) //
+ .build();
+ }
+
+ private static WebClient createWebClient(String baseUrl, SslContext sslContext) {
+ TcpClient tcpClient = TcpClient.create() //
+ .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
+ .secure(c -> c.sslContext(sslContext)) //
+ .doOnConnected(connection -> {
+ connection.addHandler(new ReadTimeoutHandler(10));
+ connection.addHandler(new WriteTimeoutHandler(30));
+ });
+ HttpClient httpClient = HttpClient.from(tcpClient);
+ ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
+
+ return WebClient.builder() //
+ .clientConnector(connector) //
+ .baseUrl(baseUrl) //
+ .build();
+ }
+
+ private Mono<WebClient> getWebClient() {
+ if (this.webClient == null) {
+ try {
+ SslContext sslContext = createSslContext();
+ this.webClient = createWebClient(this.baseUrl, sslContext);
+ } catch (SSLException e) {
+ logger.error("Could not create WebClient {}", e.getMessage());
+ return Mono.error(e);
+ }
+ }
+ return Mono.just(this.webClient);
+ }
+
+}
# A spring property but without a "spring" prefix;
# the port number is chosen RANDOMLY when running tests
-server.port = 8080
+server.port = 8434
+server.ssl.key-store-type = PKCS12
+server.ssl.key-store-password = ericsson_kwdjfhw
+server.ssl.key-store = classpath:keystore.jks
+server.ssl.key-password = ericsson_kwdjfhw
+
+
# path to file that stores user details;
# use a persistent volume in a K8S deployment
# endpoint URLs must be supplied at deployment time
# NOTE: change policycontroller.url.prefix to http://localhost:8081 when running
# controlpanel locally (i.e., not inside the docker container)
+# policycontroller.url.prefix = https://policy-agent-container:8433
policycontroller.url.prefix = http://policy-agent-container:8081
# Mimic slow endpoints by defining sleep period, in milliseconds
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.portal.nonrtric.controlpanel.config.WebSecurityMockConfiguration;
+import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@LocalServerPort
private int localServerPort;
- @Autowired
- protected TestRestTemplate restTemplate;
+ protected final AsyncRestClient webClient = new AsyncRestClient("");
/**
* Flexible URI builder.
*
- * @param queryParams
- * Map of string-string query parameters
- * @param path
- * Array of path components. If a component has an
- * embedded slash, the string is split and each
- * subcomponent is added individually.
+ * @param queryParams Map of string-string query parameters
+ * @param path Array of path components. If a component has an embedded
+ * slash, the string is split and each subcomponent is added
+ * individually.
* @return URI
*/
protected URI buildUri(final Map<String, String> queryParams, final String... path) {
- UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://localhost:" + localServerPort + "/");
+ UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("https://localhost:" + localServerPort + "/");
for (int p = 0; p < path.length; ++p) {
if (path[p] == null || path[p].isEmpty()) {
throw new IllegalArgumentException("Unexpected null or empty at path index " + Integer.toString(p));
logger.info("Context loads on mock profile");
}
- public TestRestTemplate testRestTemplateAdminRole() {
- return restTemplate.withBasicAuth(WebSecurityMockConfiguration.TEST_CRED_ADMIN,
- WebSecurityMockConfiguration.TEST_CRED_ADMIN);
- }
-
- public TestRestTemplate testRestTemplateStandardRole() {
- return restTemplate.withBasicAuth(WebSecurityMockConfiguration.TEST_CRED_STANDARD,
- WebSecurityMockConfiguration.TEST_CRED_STANDARD);
- }
-
}
*/
package org.oransc.portal.nonrtric.controlpanel.controller;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
import java.lang.invoke.MethodHandles;
import java.net.URI;
import org.onap.portalsdk.core.onboarding.util.PortalApiConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.ResponseEntity;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
public class PortalRestCentralServiceTest extends AbstractControllerTest {
// paths are hardcoded here exactly like the EPSDK-FW library :(
URI uri = buildUri(null, PortalApiConstants.API_PREFIX, "/analytics");
logger.info("Invoking {}", uri);
- ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
+ WebClientResponseException e = assertThrows(WebClientResponseException.class, () -> {
+ webClient.getForEntity(uri.toString()).block();
+ });
// No Portal is available so this always fails
- Assertions.assertTrue(response.getStatusCode().is4xxClientError());
+ Assertions.assertTrue(e.getStatusCode().is4xxClientError());
}
@Test
public void getErrorPageTest() {
// Send unauthorized request
+
URI uri = buildUri(null, "/favicon.ico");
logger.info("Invoking {}", uri);
- ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, null, String.class);
- Assertions.assertTrue(response.getStatusCode().is4xxClientError());
- Assertions.assertTrue(response.getBody().contains("Static error page"));
+ WebClientResponseException e = assertThrows(WebClientResponseException.class, () -> {
+ webClient.getForEntity(uri.toString()).block();
+ });
+ Assertions.assertTrue(e.getStatusCode().is4xxClientError());
+ Assertions.assertTrue(e.getResponseBodyAsString().contains("Static error page"));
}
-
- /*
- * private HttpEntity<Object> getEntityWithHeaders(Object body) {
- * HttpHeaders headers = new HttpHeaders();
- * headers.set(PortalApIMockConfiguration.PORTAL_USERNAME_HEADER_KEY,
- * PortalApIMockConfiguration.PORTAL_USERNAME_HEADER_KEY);
- * headers.set(PortalApIMockConfiguration.PORTAL_PASSWORD_HEADER_KEY,
- * PortalApIMockConfiguration.PORTAL_PASSWORD_HEADER_KEY);
- * HttpEntity<Object> entity = new HttpEntity<>(body, headers);
- * return entity;
- * }
- *
- * private EcompUser createEcompUser(String loginId) {
- * EcompUser user = new EcompUser();
- * user.setLoginId(loginId);
- * EcompRole role = new EcompRole();
- * role.setRoleFunctions(Collections.EMPTY_SET);
- * role.setId(1L);
- * role.setName(ControlPanelConstants.ROLE_NAME_ADMIN);
- * Set<EcompRole> roles = new HashSet<>();
- * roles.add(role);
- * user.setRoles(roles);
- * return user;
- * }
- *
- * @Test
- *
- * @Test
- * public void createUserTest() {
- * final String loginId = "login1";
- * URI create = buildUri(null, PortalApiConstants.API_PREFIX, "user");
- * logger.info("Invoking {}", create);
- * HttpEntity<Object> requestEntity = getEntityWithHeaders(createEcompUser(loginId));
- * ResponseEntity<String> response = restTemplate.exchange(create, HttpMethod.POST, requestEntity, String.class);
- * Assertions.assertTrue(response.getStatusCode().is2xxSuccessful());
- * }
- *
- * @Test
- * public void updateUserTest() {
- * final String loginId = "login2";
- * URI create = buildUri(null, PortalApiConstants.API_PREFIX, "user");
- * EcompUser user = createEcompUser(loginId);
- * logger.info("Invoking {}", create);
- * HttpEntity<Object> requestEntity = getEntityWithHeaders(user);
- * // Create
- * ResponseEntity<String> response = restTemplate.exchange(create, HttpMethod.POST, requestEntity, String.class);
- * Assertions.assertTrue(response.getStatusCode().is2xxSuccessful());
- * URI update = buildUri(null, PortalApiConstants.API_PREFIX, "user", loginId);
- * user.setEmail("user@company.org");
- * requestEntity = getEntityWithHeaders(user);
- * response = restTemplate.exchange(update, HttpMethod.POST, requestEntity, String.class);
- * Assertions.assertTrue(response.getStatusCode().is2xxSuccessful());
- * }
- */
-
}
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
-import java.util.ArrayList;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
-import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.oransc.portal.nonrtric.controlpanel.model.ImmutablePolicyInfo;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyInfo;
import org.oransc.portal.nonrtric.controlpanel.model.PolicyInstances;
-import org.oransc.portal.nonrtric.controlpanel.model.PolicyType;
-import org.oransc.portal.nonrtric.controlpanel.model.PolicyTypes;
-import org.oransc.portal.nonrtric.controlpanel.policyagentapi.PolicyAgentApiImpl.RicInfo;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
+import org.oransc.portal.nonrtric.controlpanel.util.AsyncRestClient;
import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.client.HttpClientErrorException;
-import org.springframework.web.client.RestTemplate;
+import org.springframework.web.client.HttpServerErrorException;
+import reactor.core.publisher.Mono;
public class PolicyAgentApiImplTest {
- private static final String URL_PREFIX = "UrlPrefix";
private static final String URL_POLICY_SCHEMAS = "/policy_schemas";
- private static final String URL_POLICY_INSTANCES = "/policies?type={type}";
- private static final String URL_POLICY_INSTANCE = "/policy?id={id}";
- private static final String URL_PUT_POLICY = "/policy?type={type}&id={id}&ric={ric}&service={service}";
- private static final String URL_DELETE_POLICY = "/policy?id={id}";
- private static final String URL_RIC_INFO = "/rics?policyType={typeName}";
private static final String POLICY_TYPE_1_ID = "type1";
private static final String POLICY_TYPE_1_VALID = "{\"title\":\"type1\"}";
private static final String POLICY_TYPE_1_INVALID = "\"title\":\"type1\"}";
private static final String POLICY_1_VALID = "{\"policyId\":\"policy1\"}";
private static final String POLICY_1_INVALID = "\"policyId\":\"policy1\"}";
private static final String RIC_1_ID = "ric1";
- private static final String RIC_1_INFO_VALID = "{\"name\":\"ric1\",\"policyTypes\":[\"type1\"]}";
- private static final String RIC_1_INFO_INVALID = "{\"name\":\"ric1\",\"policyTypes\":\"type1\"]}";
+ private static final String RIC_1_INFO_VALID = "{\"ricName\":\"ric1\",\"policyTypes\":[\"type1\"]}";
+ private static final String RIC_1_INFO_INVALID = "{\"ricName\":\"ric1\",\"policyTypes\":\"type1\"]}";
private static final String CLIENT_ERROR_MESSAGE = "XXXXXXX";
private static com.google.gson.Gson gson = new GsonBuilder() //
PolicyAgentApiImpl apiUnderTest;
- RestTemplate restTemplateMock;
+ AsyncRestClient restClient;
@BeforeEach
public void init() {
- restTemplateMock = mock(RestTemplate.class);
- apiUnderTest = new PolicyAgentApiImpl(URL_PREFIX, restTemplateMock);
+ restClient = mock(AsyncRestClient.class);
+ apiUnderTest = new PolicyAgentApiImpl(restClient);
+ }
+
+ private void whenGetReturnOK(String url, HttpStatus status, String body) {
+ ResponseEntity<String> ret = new ResponseEntity<>(body, status);
+ when(restClient.getForEntity(eq(url))).thenReturn(Mono.just(ret));
+ }
+
+ private void whenGetReturnFailure(String url, HttpStatus status, String body) {
+ HttpServerErrorException e = new HttpServerErrorException(status, body);
+ when(restClient.getForEntity(eq(url))).thenReturn(Mono.error(e));
}
@Test
public void testGetAllPolicyTypesFailure() {
- ResponseEntity<String> getAllPolicyTypesResp = new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_SCHEMAS), eq(String.class)))
- .thenReturn(getAllPolicyTypesResp);
-
+ whenGetReturnFailure(URL_POLICY_SCHEMAS, HttpStatus.NOT_FOUND, "");
ResponseEntity<String> returnedResp = apiUnderTest.getAllPolicyTypes();
-
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_SCHEMAS, String.class);
- assertNull(returnedResp.getBody());
assertEquals(HttpStatus.NOT_FOUND, returnedResp.getStatusCode());
}
@Test
public void testGetAllPolicyTypesSuccessValidJson() {
String policyTypes = Arrays.asList(POLICY_TYPE_1_VALID, POLICY_TYPE_2_VALID).toString();
- String policyTypesJson = parsePolicyTypesJson(policyTypes);
- ResponseEntity<String> getAllPolicyTypesResp = new ResponseEntity<>(policyTypes, HttpStatus.OK);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_SCHEMAS), eq(String.class)))
- .thenReturn(getAllPolicyTypesResp);
- ResponseEntity<String> returnedResp = apiUnderTest.getAllPolicyTypes();
+ whenGetReturnOK(URL_POLICY_SCHEMAS, HttpStatus.OK, policyTypes);
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_SCHEMAS, String.class);
- assertEquals(returnedResp.getBody(), policyTypesJson);
- assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
+ ResponseEntity<String> resp = apiUnderTest.getAllPolicyTypes();
+ assertTrue(resp.getBody().contains("\"name\":\"type1\""));
+ assertEquals(HttpStatus.OK, resp.getStatusCode());
}
@Test
public void testGetAllPolicyTypesSuccessInvalidJson() {
String policyTypes = Arrays.asList(POLICY_TYPE_1_INVALID, POLICY_TYPE_2_VALID).toString();
- ResponseEntity<String> getAllPolicyTypesResp = new ResponseEntity<>(policyTypes, HttpStatus.OK);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_SCHEMAS), eq(String.class)))
- .thenReturn(getAllPolicyTypesResp);
+ whenGetReturnOK(URL_POLICY_SCHEMAS, HttpStatus.OK, policyTypes);
ResponseEntity<String> returnedResp = apiUnderTest.getAllPolicyTypes();
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_SCHEMAS, String.class);
assertTrue(returnedResp.getBody().contains("Exception"));
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, returnedResp.getStatusCode());
}
+ private String urlPolicyInstances(String type) {
+ return "/policies?type=" + type;
+ }
+
@Test
public void testGetPolicyInstancesForTypeFailure() {
- ResponseEntity<String> getPolicyInstancesForTypeResp = new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
- Map<String, ?> uriVariables = Map.of("type", POLICY_TYPE_1_ID);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_INSTANCES), eq(String.class), eq(uriVariables)))
- .thenReturn(getPolicyInstancesForTypeResp);
+ whenGetReturnFailure(urlPolicyInstances(POLICY_TYPE_1_ID), HttpStatus.NOT_FOUND, "");
ResponseEntity<String> returnedResp = apiUnderTest.getPolicyInstancesForType(POLICY_TYPE_1_ID);
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_INSTANCES, String.class, uriVariables);
- assertNull(returnedResp.getBody());
assertEquals(HttpStatus.NOT_FOUND, returnedResp.getStatusCode());
}
public void testGetPolicyInstancesForTypeSuccessValidJson() {
String policyInstances = Arrays.asList(POLICY_1_VALID).toString();
String policyInstancesJson = parsePolicyInstancesJson(policyInstances);
- ResponseEntity<String> getPolicyInstancesForTypeResp = new ResponseEntity<>(policyInstances, HttpStatus.OK);
- Map<String, ?> uriVariables = Map.of("type", POLICY_TYPE_1_ID);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_INSTANCES), eq(String.class), eq(uriVariables)))
- .thenReturn(getPolicyInstancesForTypeResp);
+
+ whenGetReturnOK(urlPolicyInstances(POLICY_TYPE_1_ID), HttpStatus.OK, policyInstances);
ResponseEntity<String> returnedResp = apiUnderTest.getPolicyInstancesForType(POLICY_TYPE_1_ID);
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_INSTANCES, String.class, uriVariables);
assertEquals(returnedResp.getBody(), policyInstancesJson);
assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
}
@Test
public void testGetPolicyInstancesForTypeSuccessInvalidJson() {
String policyInstances = Arrays.asList(POLICY_1_INVALID).toString();
- ResponseEntity<String> getPolicyInstancesForTypeResp = new ResponseEntity<>(policyInstances, HttpStatus.OK);
- Map<String, ?> uriVariables = Map.of("type", POLICY_TYPE_1_ID);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_INSTANCES), eq(String.class), eq(uriVariables)))
- .thenReturn(getPolicyInstancesForTypeResp);
+
+ whenGetReturnOK(urlPolicyInstances(POLICY_TYPE_1_ID), HttpStatus.OK, policyInstances);
ResponseEntity<String> returnedResp = apiUnderTest.getPolicyInstancesForType(POLICY_TYPE_1_ID);
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_INSTANCES, String.class, uriVariables);
assertTrue(returnedResp.getBody().contains("Exception"));
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, returnedResp.getStatusCode());
}
+ private String urlPolicyInstance(String id) {
+ return "/policy?id=" + id;
+ }
+
@Test
public void testGetPolicyInstance() {
- ResponseEntity<Object> getPolicyInstanceResp = new ResponseEntity<>(POLICY_1_VALID, HttpStatus.OK);
- Map<String, ?> uriVariables = Map.of("id", POLICY_1_ID);
- when(restTemplateMock.getForEntity(eq(URL_PREFIX + URL_POLICY_INSTANCE), eq(Object.class), eq(uriVariables)))
- .thenReturn(getPolicyInstanceResp);
+ whenGetReturnOK(urlPolicyInstance(POLICY_1_ID), HttpStatus.OK, POLICY_1_VALID);
ResponseEntity<Object> returnedResp = apiUnderTest.getPolicyInstance(POLICY_1_ID);
- verify(restTemplateMock).getForEntity(URL_PREFIX + URL_POLICY_INSTANCE, Object.class, uriVariables);
- assertEquals(POLICY_1_VALID, returnedResp.getBody());
assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
+ assertEquals(POLICY_1_VALID, returnedResp.getBody());
+
+ }
+
+ private String urlPutPolicy(String type, String id, String ric) {
+ return "/policy?type=" + type + "&id=" + id + "&ric=" + ric + "&service=controlpanel";
+ }
+
+ private void whenPutReturnOK(String url, String putBody, HttpStatus status, String body) {
+ ResponseEntity<String> ret = new ResponseEntity<>(body, status);
+ when(restClient.putForEntity(eq(url), eq(putBody))).thenReturn(Mono.just(ret));
+ }
+
+ private void whenPutReturnFailure(String url, String putBody, HttpStatus status, String body) {
+ HttpServerErrorException e =
+ new HttpServerErrorException(status, body, body.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+ when(restClient.putForEntity(eq(url), eq(putBody))).thenReturn(Mono.error(e));
}
@Test
public void testPutPolicyFailure() {
- HttpEntity<Object> jsonHttpEntity = createJsonHttpEntity(POLICY_1_VALID);
- Map<String, ?> uriVariables = Map.of( //
- "type", POLICY_TYPE_1_ID, //
- "id", POLICY_1_ID, //
- "ric", RIC_1_ID, //
- "service", "controlpanel");
- HttpClientErrorException exception = new HttpClientErrorException(HttpStatus.NOT_FOUND, CLIENT_ERROR_MESSAGE);
- doThrow(exception).when(restTemplateMock).put(eq(URL_PREFIX + URL_PUT_POLICY), eq(jsonHttpEntity),
- eq(uriVariables));
+ String url = urlPutPolicy(POLICY_TYPE_1_ID, POLICY_1_ID, RIC_1_ID);
+ whenPutReturnFailure(url, POLICY_1_VALID, HttpStatus.NOT_FOUND, CLIENT_ERROR_MESSAGE);
ResponseEntity<String> returnedResp =
apiUnderTest.putPolicy(POLICY_TYPE_1_ID, POLICY_1_ID, POLICY_1_VALID, RIC_1_ID);
- verify(restTemplateMock).put(URL_PREFIX + URL_PUT_POLICY, jsonHttpEntity, uriVariables);
assertTrue(returnedResp.getBody().contains(CLIENT_ERROR_MESSAGE));
assertEquals(HttpStatus.NOT_FOUND, returnedResp.getStatusCode());
}
@Test
public void testPutPolicySuccess() {
- HttpEntity<Object> jsonHttpEntity = createJsonHttpEntity(POLICY_1_VALID);
- Map<String, ?> uriVariables = Map.of( //
- "type", POLICY_TYPE_1_ID, //
- "id", POLICY_1_ID, //
- "ric", RIC_1_ID, //
- "service", "controlpanel");
+ String url = urlPutPolicy(POLICY_TYPE_1_ID, POLICY_1_ID, RIC_1_ID);
+ whenPutReturnOK(url, POLICY_1_VALID, HttpStatus.OK, POLICY_1_VALID);
ResponseEntity<String> returnedResp =
apiUnderTest.putPolicy(POLICY_TYPE_1_ID, POLICY_1_ID, POLICY_1_VALID, RIC_1_ID);
- verify(restTemplateMock).put(URL_PREFIX + URL_PUT_POLICY, jsonHttpEntity, uriVariables);
assertNull(returnedResp.getBody());
assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
}
+ private void whenDeleteReturnOK(String url, HttpStatus status) {
+ ResponseEntity<String> ret = new ResponseEntity<>(status);
+ when(restClient.deleteForEntity(eq(url))).thenReturn(Mono.just(ret));
+ }
+
+ private void whenDeleteReturnFailure(String url, HttpStatus status, String body) {
+ HttpServerErrorException e =
+ new HttpServerErrorException(status, body, body.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+ when(restClient.deleteForEntity(eq(url))).thenReturn(Mono.error(e));
+ }
+
+ private String deletePolicyUrl(String id) {
+ return "/policy?id=" + id;
+ }
+
@Test
public void testDeletePolicyFailure() {
- Map<String, ?> uriVariables = Map.of("id", POLICY_1_ID);
- HttpClientErrorException exception = new HttpClientErrorException(HttpStatus.NOT_FOUND, CLIENT_ERROR_MESSAGE);
- doThrow(exception).when(restTemplateMock).delete(eq(URL_PREFIX + URL_DELETE_POLICY), eq(uriVariables));
+ whenDeleteReturnFailure(deletePolicyUrl(POLICY_1_ID), HttpStatus.NOT_FOUND, CLIENT_ERROR_MESSAGE);
ResponseEntity<String> returnedResp = apiUnderTest.deletePolicy(POLICY_1_ID);
- verify(restTemplateMock).delete(URL_PREFIX + URL_DELETE_POLICY, uriVariables);
assertTrue(returnedResp.getBody().contains(CLIENT_ERROR_MESSAGE));
assertEquals(HttpStatus.NOT_FOUND, returnedResp.getStatusCode());
}
@Test
public void testDeletePolicySuccess() {
- Map<String, ?> uriVariables = Map.of("id", POLICY_1_ID);
-
+ whenDeleteReturnOK(deletePolicyUrl(POLICY_1_ID), HttpStatus.OK);
ResponseEntity<String> returnedResp = apiUnderTest.deletePolicy(POLICY_1_ID);
- verify(restTemplateMock).delete(URL_PREFIX + URL_DELETE_POLICY, uriVariables);
- assertNull(returnedResp.getBody());
assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
}
+ private String urlRicInfo(String typeName) {
+ return "/rics?policyType=" + typeName;
+ }
+
@Test
public void testGetRicsSupportingTypeValidJson() {
String rics = Arrays.asList(RIC_1_INFO_VALID).toString();
- String ricsJson = parseRicsJson(rics);
- Map<String, ?> uriVariables = Map.of("typeName", POLICY_TYPE_1_ID);
- when(restTemplateMock.getForObject(eq(URL_PREFIX + URL_RIC_INFO), eq(String.class), eq(uriVariables)))
- .thenReturn(rics);
- ResponseEntity<String> returnedResp = apiUnderTest.getRicsSupportingType(POLICY_TYPE_1_ID);
+ this.whenGetReturnOK(urlRicInfo(POLICY_TYPE_1_ID), HttpStatus.OK, rics);
- verify(restTemplateMock).getForObject(URL_PREFIX + URL_RIC_INFO, String.class, uriVariables);
- assertEquals(returnedResp.getBody(), ricsJson);
- assertEquals(HttpStatus.OK, returnedResp.getStatusCode());
+ ResponseEntity<String> resp = apiUnderTest.getRicsSupportingType(POLICY_TYPE_1_ID);
+
+ assertEquals(HttpStatus.OK, resp.getStatusCode());
+ assertEquals("[\"ric1\"]", resp.getBody());
}
@Test
public void testGetRicsSupportingTypeInvalidJson() {
String rics = Arrays.asList(RIC_1_INFO_INVALID).toString();
- Map<String, ?> uriVariables = Map.of("typeName", POLICY_TYPE_1_ID);
- when(restTemplateMock.getForObject(eq(URL_PREFIX + URL_RIC_INFO), eq(String.class), eq(uriVariables)))
- .thenReturn(rics);
+
+ this.whenGetReturnOK(urlRicInfo(POLICY_TYPE_1_ID), HttpStatus.OK, rics);
ResponseEntity<String> returnedResp = apiUnderTest.getRicsSupportingType(POLICY_TYPE_1_ID);
- verify(restTemplateMock).getForObject(URL_PREFIX + URL_RIC_INFO, String.class, uriVariables);
assertTrue(returnedResp.getBody().contains("Exception"));
assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, returnedResp.getStatusCode());
}
- private String parsePolicyTypesJson(String inputString) {
- PolicyTypes policyTypes = new PolicyTypes();
- JsonArray schemas = JsonParser.parseString(inputString).getAsJsonArray();
- for (JsonElement schema : schemas) {
- JsonObject schemaObj = schema.getAsJsonObject();
- policyTypes.add(new PolicyType(schemaObj.get("title").getAsString(), schemaObj.toString()));
- }
- return gson.toJson(policyTypes);
- }
-
private String parsePolicyInstancesJson(String inputString) {
Type listType = new TypeToken<List<ImmutablePolicyInfo>>() {}.getType();
List<PolicyInfo> rspParsed = gson.fromJson(inputString, listType);
}
return gson.toJson(policyInstances);
}
-
- private String parseRicsJson(String inputString) {
- Type listType = new TypeToken<List<ImmutableRicInfo>>() {}.getType();
- List<RicInfo> rspParsed = gson.fromJson(inputString, listType);
- Collection<String> rics = new ArrayList<>(rspParsed.size());
- for (RicInfo ric : rspParsed) {
- rics.add(ric.ricName());
- }
- return gson.toJson(rics);
- }
-
- private HttpEntity<Object> createJsonHttpEntity(Object content) {
- HttpHeaders headers = new HttpHeaders();
- headers.setContentType(MediaType.APPLICATION_JSON);
- return new HttpEntity<>(content, headers);
- }
}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 Nordix Foundation
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.portal.nonrtric.controlpanel.util;
+
+import io.netty.util.internal.logging.InternalLoggerFactory;
+import io.netty.util.internal.logging.JdkLoggerFactory;
+
+import java.io.IOException;
+
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+import reactor.util.Loggers;
+
+public class AsyncRestClientTest {
+ private static final String BASE_URL = "BaseUrl";
+ private static final String REQUEST_URL = "/test";
+ private static final String TEST_JSON = "{\"type\":\"type1\"}";
+ private static final int SUCCESS_CODE = 200;
+ private static final int ERROR_CODE = 500;
+
+ private static MockWebServer mockWebServer;
+
+ private static AsyncRestClient clientUnderTest;
+
+ @BeforeAll
+ public static void init() {
+ // skip a lot of unnecessary logs from MockWebServer
+ InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);
+ Loggers.useJdkLoggers();
+ mockWebServer = new MockWebServer();
+ clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString());
+ }
+
+ @AfterAll
+ public static void tearDown() throws IOException {
+ mockWebServer.shutdown();
+ }
+
+ @Test
+ public void testGetNoError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
+ .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
+ .setBody(TEST_JSON));
+
+ Mono<String> returnedMono = clientUnderTest.get(REQUEST_URL);
+ StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
+ }
+
+ @Test
+ public void testGetError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
+
+ Mono<String> returnedMono = clientUnderTest.get(REQUEST_URL);
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
+ }
+
+ @Test
+ public void testPutNoError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
+ .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
+ .setBody(TEST_JSON));
+
+ Mono<String> returnedMono = clientUnderTest.put(REQUEST_URL, TEST_JSON);
+ StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
+ }
+
+ @Test
+ public void testPutError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
+
+ Mono<String> returnedMono = clientUnderTest.put(REQUEST_URL, TEST_JSON);
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
+ }
+
+ @Test
+ public void testDeleteNoError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE));
+
+ Mono<String> returnedMono = clientUnderTest.delete(REQUEST_URL);
+ StepVerifier.create(returnedMono).expectNext("").expectComplete().verify();
+ }
+
+ @Test
+ public void testDeleteError() {
+ mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
+
+ Mono<String> returnedMono = clientUnderTest.delete(REQUEST_URL);
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
+ }
+
+}