From 18866635ab8e8748bcb9e4bafb341265539ab53d Mon Sep 17 00:00:00 2001 From: bedroomghost Date: Sun, 20 Apr 2025 18:02:22 +0200 Subject: [PATCH] test: Add unit tests for PriceService and PriceRepositoryAdapter --- README.md | 33 +++++++- .../services/PriceServiceTest.java | 77 ++++++++++++++++++ infrastructure/in/rest-api/pom.xml | 18 ----- .../adapters/PriceRepositoryAdapterTest.java | 78 +++++++++++++++++++ pom.xml | 18 +++++ 5 files changed, 205 insertions(+), 19 deletions(-) create mode 100644 application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java create mode 100644 infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java diff --git a/README.md b/README.md index 91bc1cd..cb70863 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,33 @@ -# web-price +Prices web service (web-price) +=================================== +Web service for obtaining the price of a product given a date, the product id and the brand id. + +## Requirements + +- Java 21 +- Maven + +## Development + +1. Local installation of the project + ``` + mvn clean install + ``` +2. Run the app from the project root with: + ``` + mvn clean spring-boot:run -pl boot -Dspring-boot.run.profiles=local + ``` + or navigating to the `boot` directory of the project: + ``` + mvn clean spring-boot:run -Dspring-boot.run.profiles=local + ``` +3. Service should be ready to receive requests at http://localhost:8080/price with OpenAPI docs available at http://localhost:8080/swagger-ui/index.html + +## Running Tests + +To run all tests in the project: + +```bash +mvn test +``` diff --git a/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java b/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java new file mode 100644 index 0000000..2a61a80 --- /dev/null +++ b/application/src/test/java/com/techivw/webprice/application/services/PriceServiceTest.java @@ -0,0 +1,77 @@ +package com.techivw.webprice.application.services; + +import com.techivw.webprice.application.exceptions.NotFoundException; +import com.techivw.webprice.application.ports.in.PriceServicePort; +import com.techivw.webprice.application.ports.out.PriceRepositoryPort; +import com.techivw.webprice.domain.Price; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; + +@ExtendWith(SpringExtension.class) +class PriceServiceTest { + + @Mock + private PriceRepositoryPort priceRepositoryPort; + + private PriceServicePort priceService; + + private final LocalDateTime TEST_DATE = LocalDateTime.parse("2023-01-01T12:00:00"); + private final Long TEST_PRODUCT_ID = 35455L; + private final Long TEST_BRAND_ID = 1L; + + @BeforeEach + void setUp() { + priceService = new PriceService(priceRepositoryPort); + } + + @Test + void shouldReturnPriceWhenPriceExists() { + Price expectedPrice = createPrice(); + when(priceRepositoryPort.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId( + eq(TEST_DATE), eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + .thenReturn(Optional.of(expectedPrice)); + + Price result = priceService.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId( + TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID); + + assertNotNull(result); + assertEquals(expectedPrice.getProductId(), result.getProductId()); + assertEquals(expectedPrice.getPrice(), result.getPrice()); + } + + @Test + void shouldThrowNotFoundExceptionWhenPriceDoesNotExist() { + when(priceRepositoryPort.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId( + any(LocalDateTime.class), anyLong(), anyLong())) + .thenReturn(Optional.empty()); + + assertThrows(NotFoundException.class, () -> + priceService.getPriceWithHighestPriorityByDateTimeAndProductIdAndBrandId( + TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID)); + } + + private Price createPrice() { + return Price.builder() + .brandId(TEST_BRAND_ID) + .productId(TEST_PRODUCT_ID) + .startDate(TEST_DATE.minusDays(1)) + .endDate(TEST_DATE.plusDays(1)) + .priceList(1L) + .price(BigDecimal.valueOf(35.50)) + .priority(1) + .currency("EUR") + .build(); + } +} \ No newline at end of file diff --git a/infrastructure/in/rest-api/pom.xml b/infrastructure/in/rest-api/pom.xml index 9ad6546..de49e08 100644 --- a/infrastructure/in/rest-api/pom.xml +++ b/infrastructure/in/rest-api/pom.xml @@ -16,12 +16,6 @@ rest-api - - org.springframework.boot - spring-boot-starter-test - test - - com.techivw domain @@ -34,16 +28,4 @@ - - - - org.apache.maven.plugins - maven-surefire-plugin - - -javaagent:${settings.localRepository}/net/bytebuddy/byte-buddy-agent/1.15.11/byte-buddy-agent-1.15.11.jar - - - - - diff --git a/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java b/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java new file mode 100644 index 0000000..a260ca5 --- /dev/null +++ b/infrastructure/out/sql-repository/src/test/java/com/techivw/webprice/infrastructure/repositories/adapters/PriceRepositoryAdapterTest.java @@ -0,0 +1,78 @@ +package com.techivw.webprice.infrastructure.repositories.adapters; + +import com.techivw.webprice.domain.Price; +import com.techivw.webprice.infrastructure.repositories.PriceEntityJPARepository; +import com.techivw.webprice.infrastructure.repositories.model.PriceEntity; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class PriceRepositoryAdapterTest { + + @Mock + private PriceEntityJPARepository repository; + + private PriceRepositoryAdapter adapter; + + private final LocalDateTime TEST_DATE = LocalDateTime.parse("2023-01-01T12:00:00"); + private final Long TEST_PRODUCT_ID = 35455L; + private final Long TEST_BRAND_ID = 1L; + + @BeforeEach + void setUp() { + adapter = new PriceRepositoryAdapter(repository); + } + + @Test + void shouldReturnPriceWhenPriceEntityExists() { + PriceEntity priceEntity = createSamplePriceEntity(); + when(repository.findPriceByDateTimeAndProductIdAndBrandId( + eq(TEST_DATE), eq(TEST_PRODUCT_ID), eq(TEST_BRAND_ID))) + .thenReturn(Optional.of(priceEntity)); + + Optional result = adapter.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId( + TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID); + + assertTrue(result.isPresent()); + Price price = result.get(); + assertEquals(TEST_PRODUCT_ID, price.getProductId()); + assertEquals(TEST_BRAND_ID, price.getBrandId()); + assertEquals(BigDecimal.valueOf(35.50), price.getPrice()); + } + + @Test + void shouldReturnEmptyOptionalWhenPriceEntityDoesNotExist() { + when(repository.findPriceByDateTimeAndProductIdAndBrandId( + any(LocalDateTime.class), anyLong(), anyLong())) + .thenReturn(Optional.empty()); + + Optional result = adapter.findHighestPriorityPriceByDateTimeAndProductIdAndBrandId( + TEST_DATE, TEST_PRODUCT_ID, TEST_BRAND_ID); + + assertFalse(result.isPresent()); + } + + private PriceEntity createSamplePriceEntity() { + PriceEntity entity = new PriceEntity(); + entity.setBrandId(TEST_BRAND_ID); + entity.setProductId(TEST_PRODUCT_ID); + entity.setStartDate(TEST_DATE.minusDays(1)); + entity.setEndDate(TEST_DATE.plusDays(1)); + entity.setPriceList(1L); + entity.setPrice(BigDecimal.valueOf(35.50)); + entity.setPriority(1); + entity.setCurrency("EUR"); + return entity; + } +} diff --git a/pom.xml b/pom.xml index 60e4ead..13ffae0 100644 --- a/pom.xml +++ b/pom.xml @@ -51,5 +51,23 @@ springdoc-openapi-starter-webmvc-ui 2.8.6 + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -javaagent:${settings.localRepository}/net/bytebuddy/byte-buddy-agent/1.15.11/byte-buddy-agent-1.15.11.jar + + + + +