From 25efd807d1817a6404c8c98f65ad82b7b6d9d192 Mon Sep 17 00:00:00 2001 From: Mohammad Date: Thu, 26 Jun 2025 10:41:47 +0300 Subject: [PATCH] Add tests for empty product response and enhance product fetching logic --- pom.xml | 19 +++++++ .../copilotdemo/services/ProductsService.kt | 53 +++++++++++++++++++ .../controllers/ProductsControllerTest.kt | 13 +++++ 3 files changed, 85 insertions(+) diff --git a/pom.xml b/pom.xml index b98eaac..cb6ca19 100644 --- a/pom.xml +++ b/pom.xml @@ -47,6 +47,25 @@ org.jetbrains.kotlin kotlin-stdlib + + + io.cucumber + cucumber-spring + 7.23.0 + + + + io.cucumber + cucumber-junit-platform-engine + 7.23.0 + test + + + + io.cucumber + cucumber-java + 7.23.0 + org.springframework.boot diff --git a/src/main/kotlin/com/example/copilotdemo/services/ProductsService.kt b/src/main/kotlin/com/example/copilotdemo/services/ProductsService.kt index 537c2f5..f8c1f34 100644 --- a/src/main/kotlin/com/example/copilotdemo/services/ProductsService.kt +++ b/src/main/kotlin/com/example/copilotdemo/services/ProductsService.kt @@ -30,6 +30,14 @@ class ProductsService { val total: Int ) + + /** + * Retrieves a paginated list of products and the total count from the external DummyJSON API. + * + * @param start The starting index (number of products to skip). + * @param size The number of products to retrieve. + * @return [ProductsResult] containing the list of products and the total count. + */ fun getProductsAndTotal(start: Int, size: Int): ProductsResult { if (start < 0 || size < 1) return ProductsResult(emptyList(), 0) val url = UriComponentsBuilder.fromUriString(baseUrl) @@ -37,6 +45,7 @@ class ProductsService { .queryParam("limit", size) .toUriString() val response = restTemplate.getForObject(url, DummyJsonResponse::class.java) + val products = response?.products?.map { Product( id = it.id.toLong(), @@ -50,4 +59,48 @@ class ProductsService { val total = response?.total ?: 0 return ProductsResult(products, total) } + + /** + * Fetches all products from the external API in batches of 20. + * @return ProductsResult containing all products and the total count. + */ + fun getAllProductsInBatches(): ProductsResult { + val batchSize = 20 + val firstBatch = getProductsAndTotal(0, batchSize) + val total = firstBatch.total + val allProducts = mutableListOf() + allProducts.addAll(firstBatch.products) + var fetched = firstBatch.products.size + while (fetched < total) { + val batch = getProductsAndTotal(fetched, batchSize) + allProducts.addAll(batch.products) + fetched += batch.products.size + if (batch.products.isEmpty()) break // safety check + } + return ProductsResult(allProducts, total) + } + + + } + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/kotlin/com/example/copilotdemo/controllers/ProductsControllerTest.kt b/src/test/kotlin/com/example/copilotdemo/controllers/ProductsControllerTest.kt index 164c22a..c99a2bc 100644 --- a/src/test/kotlin/com/example/copilotdemo/controllers/ProductsControllerTest.kt +++ b/src/test/kotlin/com/example/copilotdemo/controllers/ProductsControllerTest.kt @@ -16,6 +16,7 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPat import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.web.client.RestTemplate +@Suppress("SpringJavaInjectionPointsAutowiringInspection") @SpringBootTest @AutoConfigureMockMvc class ProductsControllerTest { @@ -56,6 +57,18 @@ class ProductsControllerTest { .andReturn() } + // write a test case to handle empty response from the service + @Test + fun `should return empty products when service returns no products`() { + val dummyResponse = ProductsService.DummyJsonResponse(products = emptyList(), total = 0) + Mockito.`when`( + restTemplate.getForObject(Mockito.anyString(), Mockito.eq(ProductsService.DummyJsonResponse::class.java)) + ).thenReturn(dummyResponse) + mockMvc.perform(get("/api/v1/products?start=0&size=10").accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk) + .andExpect(jsonPath("$.products").isEmpty) + .andExpect(jsonPath("$.total").value(0)) + } }