feat: Distributed tracing (#3006)

* added microservices distributed tracing pattern

* feat: Implement Microservice pattern: Distributed tracing #2693
This commit is contained in:
Walyson Moises authored and GitHub committed 2024-07-20 13:42:12 +03:00
1 parent 1d454f7721
commit 9c43d85f36
35 files changed
+1724

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

@@ -0,0 +1,15 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,15 @@
@startuml
!theme vibrant
package com.iluwatar.microservices-distributed-tracing {
package "Order Microservice" {
class OrderController {
+processOrder()
}
class OrderService {
+validateProduct()
+processPayment()
}
}
}
@enduml
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
The MIT License
Copyright © 2014-2022 Ilkka Seppälä
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>microservices-distributed-tracing</artifactId>
<groupId>com.iluwatar</groupId>
<version>1.26.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-microservice</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<configuration>
<archive>
<manifest>
<mainClass>com.iluwatar.order.microservice.com.iluwatar.product.microservice.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>central</id>
<name>Maven Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
</project>
@@ -0,0 +1,80 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* With the Microservices pattern, a request often travels through multiple different microservices.
* Tracking the entire request flow across these services can be challenging, especially when trying
* to diagnose performance issues or failures. Distributed tracing addresses this challenge by
* providing end-to-end visibility into the lifecycle of a request as it passes through various
* microservices.
*
* <p>The intent of the Distributed Tracing pattern is to trace a request across different
* microservices, collecting detailed timing data and logs that help in understanding the flow,
* performance bottlenecks, and failure points in a distributed system. Each microservice involved
* in the request contributes to the tracing data, creating a comprehensive view of the request's
* journey.
*
* <p>This implementation demonstrates distributed tracing in a microservices architecture for an
* e-commerce platform. When a customer places an order, the {@link OrderService} interacts with
* both the payment-microservice to process the payment and the product-microservice to check the
* product inventory. Tracing logs are generated for each interaction, and these logs can be
* visualized using Zipkin.
*
* <p>To run Zipkin and view the tracing logs, you can use the following Docker command:
*
* <pre>
* {@code docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin }
* </pre>
*
* <p>Start Zipkin with the command above. Once Zipkin is running, you can
* access the Zipkin UI at `<a href="http://localhost:9411">...</a>`
* to view the tracing logs and analyze the request flows across your microservices.
*
*
* <p>To place an order and generate tracing data, you can use the following curl command:
*
* <pre>
* {@code curl -X POST http://localhost:30300/order -H "Content-Type: application/json" -d '{"orderId": "123"}' }
* </pre>
*
* <p>This command sends a POST request to create an order, which will trigger interactions with the
* payment and product microservices, generating tracing logs that can be viewed in Zipkin.
*
*/
@SpringBootApplication
public class Main {
/**
* Program entry point.
*
* @param args command line args
*/
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
@@ -0,0 +1,64 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* This controller handles order processing by calling necessary microservices.
*/
@Slf4j
@RestController
public class OrderController {
private final OrderService orderService;
/**
* Constructor to inject OrderService.
*
* @param orderService the service to process orders
*/
public OrderController(final OrderService orderService) {
this.orderService = orderService;
}
/**
* Endpoint to process an order.
*
* @param request the order request body (can be null)
* @return ResponseEntity with a status message
*/
@PostMapping("/order")
public ResponseEntity<String> processOrder(@RequestBody(required = false) String request) {
LOGGER.info("Received order request: {}", request);
var result = orderService.processOrder();
LOGGER.info("Order processed result: {}", result);
return ResponseEntity.ok(result);
}
}
@@ -0,0 +1,103 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
/**
* Service to handle order processing logic.
*/
@Slf4j
@Service
public class OrderService {
private final RestTemplateBuilder restTemplateBuilder;
/**
* Constructor to inject RestTemplateBuilder.
*
* @param restTemplateBuilder the RestTemplateBuilder to build RestTemplate instances
*/
public OrderService(final RestTemplateBuilder restTemplateBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
}
/**
* Processes an order by calling
* {@link OrderService#validateProduct()} and
* {@link OrderService#processPayment()}.
*
* @return A string indicating whether the order was processed successfully or failed.
*/
public String processOrder() {
if (validateProduct() && processPayment()) {
return "Order processed successfully";
}
return "Order processing failed";
}
/**
* Validates the product by calling the respective microservice.
*
* @return true if the product is valid, false otherwise.
*/
Boolean validateProduct() {
try {
ResponseEntity<Boolean> productValidationResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30302/product/validate", "validating product",
Boolean.class);
LOGGER.info("Product validation result: {}", productValidationResult.getBody());
return productValidationResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with product service: {}", e.getMessage());
return false;
}
}
/**
* Validates the product by calling the respective microservice.
*
* @return true if the product is valid, false otherwise.
*/
Boolean processPayment() {
try {
ResponseEntity<Boolean> paymentProcessResult = restTemplateBuilder
.build()
.postForEntity("http://localhost:30301/payment/process", "processing payment",
Boolean.class);
LOGGER.info("Payment processing result: {}", paymentProcessResult.getBody());
return paymentProcessResult.getBody();
} catch (ResourceAccessException | HttpClientErrorException e) {
LOGGER.error("Error communicating with payment service: {}", e.getMessage());
return false;
}
}
}
@@ -0,0 +1,33 @@
#
# The MIT License
# Copyright © 2014-2021 Ilkka Seppälä
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
spring.application.name=order-microservice
server.port=30300
management.tracing.sampling.probability=1
logging.pattern.level=%5p [${spring.zipkin.service.name:${spring.application.name:}},%X{traceId:-},%X{spanId:-}]
management.tracing.propagation.type=w3c
management.tracing.baggage.enabled=true
management.tracing.enabled=true
management.zipkin.tracing.endpoint=http://localhost:9411/api/v2/spans
@@ -0,0 +1,39 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import org.junit.jupiter.api.Test;
/**
* Application test
*/
class MainTest {
@Test
void shouldExecuteApplicationWithoutException() {
assertDoesNotThrow(() -> Main.main(new String[]{}));
}
}
@@ -0,0 +1,76 @@
package com.iluwatar.order.microservice;/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.ResponseEntity;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
/**
* OrderControllerTest class to test the OrderController.
*/
class OrderControllerTest {
@InjectMocks
private OrderController orderController;
@Mock
private OrderService orderService;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
}
/**
* Test to process the order successfully.
*/
@Test
void processOrderShouldReturnSuccessStatus() {
// Arrange
when(orderService.processOrder()).thenReturn("Order processed successfully");
// Act
ResponseEntity<String> response = orderController.processOrder("test order");
// Assert
assertEquals("Order processed successfully", response.getBody());
}
/**
* Test to process the order with failure.
*/
@Test
void ProcessOrderShouldReturnFailureStatusWhen() {
// Arrange
when(orderService.processOrder()).thenReturn("Order processing failed");
// Act
ResponseEntity<String> response = orderController.processOrder("test order");
// Assert
assertEquals("Order processing failed", response.getBody());
}
}
@@ -0,0 +1,192 @@
/*
* This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
*
* The MIT License
* Copyright © 2014-2022 Ilkka Seppälä
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.iluwatar.order.microservice;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
/**
* OrderServiceTest class to test the OrderService.
*/
class OrderServiceTest {
@InjectMocks
private OrderService orderService;
@Mock
private RestTemplateBuilder restTemplateBuilder;
@Mock
private RestTemplate restTemplate;
@BeforeEach
void setup() {
MockitoAnnotations.openMocks(this);
when(restTemplateBuilder.build()).thenReturn(restTemplate);
}
/**
* Test to process the order successfully.
*/
@Test
void testProcessOrder_Success() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processed successfully", result);
}
/**
* Test to process the order with failure caused by product validation failure.
*/
@Test
void testProcessOrder_FailureWithProductValidationFailure() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(false));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processing failed", result);
}
/**
* Test to process the order with failure caused by payment processing failure.
*/
@Test
void testProcessOrder_FailureWithPaymentProcessingFailure() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(false));
// Act
String result = orderService.processOrder();
// Assert
assertEquals("Order processing failed", result);
}
/**
* Test to validate the product.
*/
@Test
void testValidateProduct() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(true, result);
}
/**
* Test to process the payment.
*/
@Test
void testProcessPayment() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenReturn(ResponseEntity.ok(true));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(true, result);
}
/**
* Test to validate the product with ResourceAccessException.
*/
@Test
void testValidateProduct_ResourceAccessException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenThrow(new ResourceAccessException("Service unavailable"));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(false, result);
}
/**
* Test to validate the product with HttpClientErrorException.
*/
@Test
void testValidateProduct_HttpClientErrorException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30302/product/validate"), anyString(), eq(Boolean.class)))
.thenThrow(new HttpClientErrorException(org.springframework.http.HttpStatus.BAD_REQUEST, "Bad request"));
// Act
Boolean result = orderService.validateProduct();
// Assert
assertEquals(false, result);
}
/**
* Test to process the payment with ResourceAccessException.
*/
@Test
void testProcessPayment_ResourceAccessException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenThrow(new ResourceAccessException("Service unavailable"));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(false, result);
}
/**
* Test to process the payment with HttpClientErrorException.
*/
@Test
void testProcessPayment_HttpClientErrorException() {
// Arrange
when(restTemplate.postForEntity(eq("http://localhost:30301/payment/process"), anyString(), eq(Boolean.class)))
.thenThrow(new HttpClientErrorException(org.springframework.http.HttpStatus.BAD_REQUEST, "Bad request"));
// Act
Boolean result = orderService.processPayment();
// Assert
assertEquals(false, result);
}
}