diff --git a/inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagement.java b/inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagementController.java similarity index 96% rename from inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagement.java rename to inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagementController.java index 8feda1794781629eca099fe808c7227fb84cab0b..05fc111f91923bc23cf55545991d5fcbdf6cf212 100644 --- a/inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagement.java +++ b/inventory-management/src/main/java/cz/muni/fi/pa165/controller/InventoryManagementController.java @@ -11,6 +11,7 @@ import cz.muni.fi.pa165.model.dto.ProductDTO; import cz.muni.fi.pa165.model.dto.TransactionDTO; import cz.muni.fi.pa165.model.validator.interfaces.AddGrapeValidationGroup; import cz.muni.fi.pa165.model.validator.interfaces.AddWineValidationGroup; +import cz.muni.fi.pa165.model.validator.interfaces.RestockGrapeValidationGroup; import cz.muni.fi.pa165.model.validator.interfaces.RestockWineValidationGroup; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -24,12 +25,12 @@ import org.springframework.web.bind.annotation.*; import java.util.List; @RestController -public class InventoryManagement { +public class InventoryManagementController { private final InventoryFacade inventoryFacade; @Autowired - public InventoryManagement(InventoryFacade inventoryFacade) { + public InventoryManagementController(InventoryFacade inventoryFacade) { this.inventoryFacade = inventoryFacade; } @@ -151,7 +152,7 @@ public class InventoryManagement { @ApiResponse(responseCode = "404", description = "Grape with provided code does not exist") }) @PostMapping("/grape/restock") - public ResponseEntity<HttpStatus> restockGrape(@RequestBody GrapeDTO grapeDTO) { + public ResponseEntity<HttpStatus> restockGrape(@Validated(RestockGrapeValidationGroup.class)@RequestBody GrapeDTO grapeDTO) { try { inventoryFacade.restockGrape(grapeDTO); return new ResponseEntity<>(HttpStatus.OK); diff --git a/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPIIntegrationTest.java b/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPIIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..11d83dcedcac5ed83ca313b7e99cd17581d73920 --- /dev/null +++ b/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPIIntegrationTest.java @@ -0,0 +1,302 @@ +package cz.muni.fi.pa165.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import cz.muni.fi.pa165.model.dto.GrapeDTO; +import cz.muni.fi.pa165.model.dto.IngredientDTO; +import cz.muni.fi.pa165.model.dto.ProductDTO; +import cz.muni.fi.pa165.model.dto.TransactionDTO; +import cz.muni.fi.pa165.model.Grape; +import cz.muni.fi.pa165.model.Ingredient; +import cz.muni.fi.pa165.model.InventoryItem; +import cz.muni.fi.pa165.model.Product; +import cz.muni.fi.pa165.repository.GrapeRepository; +import cz.muni.fi.pa165.repository.IngredientRepository; +import cz.muni.fi.pa165.repository.InventoryItemRepository; +import cz.muni.fi.pa165.repository.ProductRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@SpringBootTest +@AutoConfigureMockMvc +@ActiveProfiles("test") +class InventoryManagementControllerAPIIntegrationTest { + + @Autowired + private MockMvc mockMvc; + @Autowired + private ProductRepository productRepository; + @Autowired + private InventoryItemRepository inventoryItemRepository; + @Autowired + private GrapeRepository grapeRepository; + @Autowired + private IngredientRepository ingredientRepository; + + + @BeforeEach + void setUp() { + Product wine = productRepository.findByProductCode("test-code"); + if (wine == null) { + wine = new Product(); + wine.setProductName("Test Wine"); + wine.setProductCode("test-code"); + wine.setDescription("Test Wine Description"); + wine.setQuantityAvailable(100); + wine.setPrice(10.0); + productRepository.save(wine); + } + + InventoryItem inventoryItem = inventoryItemRepository.findByProductProductCode(wine.getProductCode()); + if (inventoryItem == null) { + inventoryItem = new InventoryItem(); + inventoryItem.setProduct(wine); + inventoryItem.setQuantity(100); + inventoryItemRepository.save(inventoryItem); + } + + Grape testGrape = grapeRepository.findByCode("test-code"); + if (testGrape == null) { + testGrape = new Grape(); + testGrape.setName("Test Grape"); + testGrape.setCode("test-code"); + testGrape.setDescription("Test Grape Description"); + grapeRepository.save(testGrape); + } + + Ingredient testIngredient = ingredientRepository.findByName("Test Ingredient"); + if (testIngredient == null) { + testIngredient = new Ingredient(); + testIngredient.setName("Test Ingredient"); + ingredientRepository.save(testIngredient); + } + } + + @Test + void getWineList() throws Exception { + mockMvc.perform(get("/wine/list")) + .andExpect(status().isOk()); + } + + + @Test + void getWineById_Success() throws Exception { + + mockMvc.perform(get("/wine/1")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.name", is("Test Wine"))) + .andExpect(jsonPath("$.code", is("test-code"))); + } + + @Test + void getWineById_Failure() throws Exception { + mockMvc.perform(get("/wine/999")) + .andExpect(status().isNotFound()); + } + + @Test + void getWineByCode_Success() throws Exception { + mockMvc.perform(get("/wine/code/test-code")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.name", is("Test Wine"))) + .andExpect(jsonPath("$.code", is("test-code"))); + } + + @Test + void getWineByCode_Failure() throws Exception { + mockMvc.perform(get("/wine/code/non-existing-code")) + .andExpect(status().isNotFound()); + } + + @Test + void addWine_Success() throws Exception { + // Create a new wine + ProductDTO newWine = new ProductDTO(); + newWine.setName("New Wine"); + newWine.setCode("new-code"); + newWine.setDescription("New Wine Description"); + newWine.setPrice(10.0); + + mockMvc.perform(post("/wine/create") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(newWine))) + .andExpect(status().isCreated()); + } + + @Test + void addWine_Failure() throws Exception { + ProductDTO newWine = new ProductDTO(); + newWine.setName("New Wine"); + newWine.setCode("test-code"); + newWine.setDescription("New Wine Description"); + newWine.setPrice(10.0); + + mockMvc.perform(post("/wine/create") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(newWine))) + .andExpect(status().isConflict()); + } + + @Test + void restockWine_Success() throws Exception { + // Create a new wine + ProductDTO restockWine = new ProductDTO(); + restockWine.setName("Test Wine"); + restockWine.setCode("test-code"); + + mockMvc.perform(post("/wine/restock") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(restockWine))) + .andExpect(status().isOk()); + } + + @Test + void restockWine_Failure() throws Exception { + ProductDTO restockWine = new ProductDTO(); + restockWine.setName("Non-existing Wine"); + restockWine.setCode("non-existing-code"); + + mockMvc.perform(post("/wine/restock") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(restockWine))) + .andExpect(status().isNotFound()); + } + + @Test + void createTransaction_Success() throws Exception { + TransactionDTO newTransaction = new TransactionDTO(); + newTransaction.setProductCode("test-code"); + newTransaction.setTransactionType("Sale"); + newTransaction.setQuantity(10); + + mockMvc.perform(post("/transaction/create") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(newTransaction))) + .andExpect(status().isCreated()); + + } + + @Test + void getGrapeList_Success() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/grape/list")) + .andExpect(status().isOk()); + } + + @Test + void getGrapeByCode_Success() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/grape/test-code")) + .andExpect(status().isOk()); + } + + @Test + void getGrapeByCode_Failure() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/grape/non-existing-code")) + .andExpect(status().isNotFound()); + } + + @Test + void createGrape_Success() throws Exception { + // Create a new grape + GrapeDTO newGrape = new GrapeDTO(); + newGrape.setName("New Grape"); + newGrape.setCode("new-code"); + newGrape.setDescription("New Grape Description"); + + // Perform the request and assert the response + mockMvc.perform(post("/grape/create") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(newGrape))) + .andExpect(status().isCreated()); + } + + @Test + void createGrape_Failure() throws Exception { + // Create a new grape with an existing code + GrapeDTO newGrape = new GrapeDTO(); + newGrape.setName("New Grape"); + newGrape.setCode("test-code"); + newGrape.setDescription("New Grape Description"); + + // Perform the request and assert the response + mockMvc.perform(post("/grape/create") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(newGrape))) + .andExpect(status().isConflict()); + } + + @Test + void restockGrape_Success() throws Exception { + // Create a new grape + GrapeDTO restockGrape = new GrapeDTO(); + restockGrape.setName("Test Grape"); + restockGrape.setCode("test-code"); + + // Perform the request and assert the response + mockMvc.perform(post("/grape/restock") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(restockGrape))) + .andExpect(status().isOk()); + } + + @Test + void restockGrape_Failure() throws Exception { + // Create a new grape with a non-existing code + GrapeDTO restockGrape = new GrapeDTO(); + restockGrape.setName("Non-existing Grape"); + restockGrape.setCode("non-existing-code"); + + // Perform the request and assert the response + mockMvc.perform(post("/grape/restock") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(restockGrape))) + .andExpect(status().isNotFound()); + } + + @Test + void getIngredientList_Success() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/ingredient/list")) + .andExpect(status().isOk()); + } + + @Test + void getIngredientByName_Success() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/ingredient/Test Ingredient")) + .andExpect(status().isOk()); + } + + @Test + void getIngredientByName_Failure() throws Exception { + // Perform the request and assert the response + mockMvc.perform(get("/ingredient/non-existing-name")) + .andExpect(status().isNotFound()); + } + + @Test + void restockIngredient_Success() throws Exception { + // Create a new ingredient + IngredientDTO restockIngredient = new IngredientDTO(); + restockIngredient.setName("Test Ingredient"); + + // Perform the request and assert the response + mockMvc.perform(post("/ingredient/restock") + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(restockIngredient))) + .andExpect(status().isCreated()); + } +} diff --git a/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPITest.java b/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPITest.java new file mode 100644 index 0000000000000000000000000000000000000000..5611673072d809dfb06c9785b669d0c2e44fed77 --- /dev/null +++ b/inventory-management/src/test/java/cz/muni/fi/pa165/controller/InventoryManagementControllerAPITest.java @@ -0,0 +1,332 @@ +package cz.muni.fi.pa165.controller; + +import cz.muni.fi.pa165.exceptions.GrapeAlreadyExistsException; +import cz.muni.fi.pa165.exceptions.GrapeDoesNotExistException; +import cz.muni.fi.pa165.exceptions.ProductAlreadyExistsException; +import cz.muni.fi.pa165.exceptions.ProductNotFoundException; +import cz.muni.fi.pa165.facade.InventoryFacade; +import cz.muni.fi.pa165.model.dto.GrapeDTO; +import cz.muni.fi.pa165.model.dto.IngredientDTO; +import cz.muni.fi.pa165.model.dto.ProductDTO; +import cz.muni.fi.pa165.model.dto.TransactionDTO; +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.HttpStatus; +import org.springframework.http.ResponseEntity; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class InventoryManagementControllerAPITest { + + @Mock + private InventoryFacade inventoryFacade; + + @InjectMocks + private InventoryManagementController inventoryManagementController; + + private final ProductDTO testProduct = new ProductDTO("test", "test", 2, "code"); + private final GrapeDTO testGrape = new GrapeDTO(); + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + } + + @Test + void getWineListReturnsOkWhenWinesExist() { + // arrange + List<ProductDTO> wines = List.of(testProduct); + when(inventoryFacade.getWineList(0, 10)).thenReturn(wines); + + // act + ResponseEntity<List<ProductDTO>> result = inventoryManagementController.getWineList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(wines, result.getBody()); + } + + @Test + void getWineListReturnsOkWhenNoWinesExist() { + // arrange + when(inventoryFacade.getWineList(0, 10)).thenReturn(List.of()); + + // act + ResponseEntity<List<ProductDTO>> result = inventoryManagementController.getWineList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertTrue(result.getBody().isEmpty()); + } + + @Test + void getWineByIdReturnsOkWhenWineExists() { + // arrange + when(inventoryFacade.getWineById(1L)).thenReturn(testProduct); + + // act + ResponseEntity<ProductDTO> result = inventoryManagementController.getWineById(1L); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(testProduct, result.getBody()); + } + + @Test + void getWineByIdReturnsNotFoundWhenWineDoesNotExist() { + // arrange + when(inventoryFacade.getWineById(1L)).thenReturn(null); + + // act + ResponseEntity<ProductDTO> result = inventoryManagementController.getWineById(1L); + + // assert + assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); + } + + @Test + void getWineByCodeReturnsOkWhenWineExists() { + when(inventoryFacade.getWineByCode("code")).thenReturn(testProduct); + + ResponseEntity<ProductDTO> result = inventoryManagementController.getWineByCode("code"); + + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(testProduct, result.getBody()); + } + + @Test + void getWineByCodeReturnsNotFoundWhenWineDoesNotExist() { + when(inventoryFacade.getWineByCode("code")).thenReturn(null); + + ResponseEntity<ProductDTO> result = inventoryManagementController.getWineByCode("code"); + + assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); + } + + @Test + void addWineReturnsCreatedWhenSuccessful() throws ProductAlreadyExistsException { + // arrange + doNothing().when(inventoryFacade).addWine(testProduct); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.addWine(testProduct); + + // assert + assertEquals(HttpStatus.CREATED, result.getStatusCode()); + } + + @Test + void addWineReturnsConflictWhenProductAlreadyExists() throws ProductAlreadyExistsException { + // arrange + doThrow(ProductAlreadyExistsException.class).when(inventoryFacade).addWine(testProduct); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.addWine(testProduct); + + // assert + assertEquals(HttpStatus.CONFLICT, result.getStatusCode()); + } + + @Test + void restockWineReturnsOkWhenSuccessful() throws ProductNotFoundException { + // arrange + doNothing().when(inventoryFacade).restockWine(testProduct); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.restockWine(testProduct); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + } + + @Test + void restockWineReturnsNotFoundWhenProductNotFound() throws ProductNotFoundException { + // arrange + doThrow(ProductNotFoundException.class).when(inventoryFacade).restockWine(testProduct); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.restockWine(testProduct); + + // assert + assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); + } + + @Test + void createTransactionReturnsCreatedWhenSuccessful() { + // arrange + TransactionDTO testTransaction = new TransactionDTO(); + doNothing().when(inventoryFacade).createTransaction(testTransaction); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.createTransaction(testTransaction); + + // assert + assertEquals(HttpStatus.CREATED, result.getStatusCode()); + } + + @Test + void createTransactionThrowsExceptionWhenInvalidInput() { + // arrange + TransactionDTO testTransaction = new TransactionDTO(); + doThrow(IllegalArgumentException.class).when(inventoryFacade).createTransaction(testTransaction); + + // act & assert + assertThrows(IllegalArgumentException.class, () -> inventoryManagementController.createTransaction(testTransaction)); + } + + @Test + void getGrapeListReturnsOkWhenGrapesExist() { + // arrange + List<GrapeDTO> grapes = List.of(testGrape); + when(inventoryFacade.getGrapeList(0, 10)).thenReturn(grapes); + + // act + ResponseEntity<List<GrapeDTO>> result = inventoryManagementController.getGrapeList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(grapes, result.getBody()); + } + + @Test + void getGrapeListReturnsOkWhenNoGrapesExist() { + // arrange + when(inventoryFacade.getGrapeList(0, 10)).thenReturn(List.of()); + + // act + ResponseEntity<List<GrapeDTO>> result = inventoryManagementController.getGrapeList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertTrue(result.getBody().isEmpty()); + } + @Test + void createGrapeReturnsCreatedWhenSuccessful() throws GrapeAlreadyExistsException { + // arrange + doNothing().when(inventoryFacade).createGrape(testGrape); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.createGrape(testGrape); + + // assert + assertEquals(HttpStatus.CREATED, result.getStatusCode()); + } + + @Test + void createGrapeReturnsConflictWhenGrapeAlreadyExists() throws GrapeAlreadyExistsException { + // arrange + doThrow(GrapeAlreadyExistsException.class).when(inventoryFacade).createGrape(testGrape); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.createGrape(testGrape); + + // assert + assertEquals(HttpStatus.CONFLICT, result.getStatusCode()); + } + + @Test + void restockGrapeReturnsOkWhenSuccessful() throws GrapeDoesNotExistException { + // arrange + doNothing().when(inventoryFacade).restockGrape(testGrape); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.restockGrape(testGrape); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + } + + @Test + void restockGrapeReturnsNotFoundWhenGrapeDoesNotExist() throws GrapeDoesNotExistException { + // arrange + doThrow(GrapeDoesNotExistException.class).when(inventoryFacade).restockGrape(testGrape); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.restockGrape(testGrape); + + // assert + assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); + } + + @Test + void getIngredientListReturnsOkWhenIngredientsExist() { + // arrange + List<IngredientDTO> ingredients = List.of(new IngredientDTO()); + when(inventoryFacade.getIngredientList(0, 10)).thenReturn(ingredients); + + // act + ResponseEntity<List<IngredientDTO>> result = inventoryManagementController.getIngredientList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(ingredients, result.getBody()); + } + + @Test + void getIngredientListReturnsOkWhenNoIngredientsExist() { + // arrange + when(inventoryFacade.getIngredientList(0, 10)).thenReturn(List.of()); + + // act + ResponseEntity<List<IngredientDTO>> result = inventoryManagementController.getIngredientList(0, 10); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertTrue(result.getBody().isEmpty()); + } + + @Test + void getIngredientByNameReturnsOkWhenIngredientExists() { + // arrange + IngredientDTO testIngredient = new IngredientDTO(); + when(inventoryFacade.getIngredientByName("name")).thenReturn(testIngredient); + + // act + ResponseEntity<IngredientDTO> result = inventoryManagementController.getIngredientByName("name"); + + // assert + assertEquals(HttpStatus.OK, result.getStatusCode()); + assertEquals(testIngredient, result.getBody()); + } + + @Test + void getIngredientByNameReturnsNotFoundWhenIngredientDoesNotExist() { + // arrange + when(inventoryFacade.getIngredientByName("name")).thenReturn(null); + + // act + ResponseEntity<IngredientDTO> result = inventoryManagementController.getIngredientByName("name"); + + // assert + assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); + } + + @Test + void restockIngredientReturnsCreatedWhenSuccessful() { + // arrange + IngredientDTO testIngredient = new IngredientDTO(); + doNothing().when(inventoryFacade).restockIngredient(testIngredient); + + // act + ResponseEntity<HttpStatus> result = inventoryManagementController.restockIngredient(testIngredient); + + // assert + assertEquals(HttpStatus.CREATED, result.getStatusCode()); + } + + @Test + void restockIngredientThrowsExceptionWhenInvalidInput() { + // arrange + IngredientDTO testIngredient = new IngredientDTO(); + doThrow(IllegalArgumentException.class).when(inventoryFacade).restockIngredient(testIngredient); + + // act & assert + assertThrows(IllegalArgumentException.class, () -> inventoryManagementController.restockIngredient(testIngredient)); + } +} diff --git a/inventory-management/src/test/java/cz/muni/fi/pa165/facade/InventoryFacadeTest.java b/inventory-management/src/test/java/cz/muni/fi/pa165/facade/InventoryFacadeTest.java index f17a5f69c21b1a6d5c68fe82d3c2e10e3f6ea3be..05a8bb8eb0aa331d44baa42fd3562b8a95840cad 100644 --- a/inventory-management/src/test/java/cz/muni/fi/pa165/facade/InventoryFacadeTest.java +++ b/inventory-management/src/test/java/cz/muni/fi/pa165/facade/InventoryFacadeTest.java @@ -1,13 +1,16 @@ package cz.muni.fi.pa165.facade; -import cz.muni.fi.pa165.model.dto.GrapeDTO; -import cz.muni.fi.pa165.model.dto.IngredientDTO; -import cz.muni.fi.pa165.model.dto.ProductDTO; -import cz.muni.fi.pa165.model.dto.TransactionDTO; +import cz.muni.fi.pa165.exceptions.GrapeDoesNotExistException; +import cz.muni.fi.pa165.exceptions.ProductAlreadyExistsException; +import cz.muni.fi.pa165.exceptions.ProductNotFoundException; import cz.muni.fi.pa165.model.Grape; import cz.muni.fi.pa165.model.Ingredient; import cz.muni.fi.pa165.model.Product; import cz.muni.fi.pa165.model.Transaction; +import cz.muni.fi.pa165.model.dto.GrapeDTO; +import cz.muni.fi.pa165.model.dto.IngredientDTO; +import cz.muni.fi.pa165.model.dto.ProductDTO; +import cz.muni.fi.pa165.model.dto.TransactionDTO; import cz.muni.fi.pa165.service.GrapeService; import cz.muni.fi.pa165.service.IngredientService; import cz.muni.fi.pa165.service.InventoryService; @@ -23,7 +26,7 @@ import org.mockito.MockitoAnnotations; import java.util.List; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; class InventoryFacadeTest { @@ -42,90 +45,295 @@ class InventoryFacadeTest { @InjectMocks private InventoryFacade inventoryFacade; - private final ProductDTO testProductDTO = new ProductDTO(); - private final Product testProduct = new Product(); - - private final TransactionDTO testTransactionDTO = new TransactionDTO(); - private final Transaction testTransaction = new Transaction(); - private final GrapeDTO testGrapeDTO = new GrapeDTO(); - private final Grape testGrape = new Grape(); - private final IngredientDTO testIngredientDTO = new IngredientDTO(); - private final Ingredient testIngredient = new Ingredient(); - - @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); - when(mapper.mapProductDTOToProduct(testProductDTO)).thenReturn(testProduct); - when(mapper.mapProductToDTO(testProduct)).thenReturn(testProductDTO); + } + + @Test + void shouldReturnEmptyListWhenNoWinesAvailable() { + // arrange + when(productService.getWineList(0, 10)).thenReturn(List.of()); + + // act + List<ProductDTO> result = inventoryFacade.getWineList(0, 10); + + // assert + assertTrue(result.isEmpty()); + } + + @Test + void shouldReturnWineListWhenWinesAreAvailable() { + // arrange + Product testProduct = new Product(); + ProductDTO testProductDTO = new ProductDTO(); + when(productService.getWineList(0, 10)).thenReturn(List.of(testProduct)); when(mapper.mapProductListToDTOList(List.of(testProduct))).thenReturn(List.of(testProductDTO)); - when(mapper.mapTransactionDtoToTransaction(testTransactionDTO)).thenReturn(testTransaction); - when(mapper.mapGrapeToDTO(testGrape)).thenReturn(testGrapeDTO); - when(mapper.mapGrapeDTOToGrape(testGrapeDTO)).thenReturn(testGrape); - when(mapper.mapIngredientDTOToIngredient(testIngredientDTO)).thenReturn(testIngredient); - when(mapper.mapIngredientToDTO(testIngredient)).thenReturn(testIngredientDTO); + + // act + List<ProductDTO> result = inventoryFacade.getWineList(0, 10); + + // assert + assertFalse(result.isEmpty()); + assertEquals(testProductDTO, result.getFirst()); } @Test - void getWineList() { - when(productService.getWineList(0,10)).thenReturn(List.of(testProduct)); + void shouldReturnNullWhenNoWineWithGivenIdExists() { + // arrange + when(productService.getWineById(1L)).thenReturn(null); - List<ProductDTO> result = inventoryFacade.getWineList(0,10); + // act + ProductDTO result = inventoryFacade.getWineById(1L); - assertEquals(List.of(testProductDTO), result); + // assert + assertNull(result); } @Test - void getWineById() { + void shouldReturnWineWhenWineWithGivenIdExists() { + // arrange + Product testProduct = new Product(); + ProductDTO testProductDTO = new ProductDTO(); when(productService.getWineById(1L)).thenReturn(testProduct); + when(mapper.mapProductToDTO(testProduct)).thenReturn(testProductDTO); + // act ProductDTO result = inventoryFacade.getWineById(1L); + // assert assertEquals(testProductDTO, result); } @Test - void getWineByCode() { - when(productService.getProductByCode("test-code")).thenReturn(testProduct); + void shouldThrowExceptionWhenAddingExistingWine() throws ProductAlreadyExistsException { + // arrange + ProductDTO testProductDTO = new ProductDTO(); + when(mapper.mapProductDTOToProduct(testProductDTO)).thenReturn(new Product()); + doThrow(ProductAlreadyExistsException.class).when(productService).addWine(new Product()); + + // act & assert + assertThrows(ProductAlreadyExistsException.class, () -> inventoryFacade.addWine(testProductDTO)); + } + + @Test + void shouldAddWineSuccessfullyWhenWineDoesNotExist() throws ProductAlreadyExistsException { + // arrange + ProductDTO testProductDTO = new ProductDTO(); + Product testProduct = new Product(); + when(mapper.mapProductDTOToProduct(testProductDTO)).thenReturn(testProduct); + + // act & assert + assertDoesNotThrow(() -> inventoryFacade.addWine(testProductDTO)); + verify(productService).addWine(testProduct); + } + + @Test + void shouldThrowExceptionWhenRestockingNonExistentWine() throws ProductNotFoundException { + // arrange + ProductDTO testProductDTO = new ProductDTO(); + testProductDTO.setCode("non-existent-code"); + doThrow(ProductNotFoundException.class).when(inventoryService).restockWine(testProductDTO.getCode(), testProductDTO.getQuantity()); + + // act & assert + assertThrows(ProductNotFoundException.class, () -> inventoryFacade.restockWine(testProductDTO)); + } + + @Test + void shouldRestockWineSuccessfullyWhenWineExists() throws ProductNotFoundException { + // arrange + ProductDTO testProductDTO = new ProductDTO(); + testProductDTO.setCode("existent-code"); + testProductDTO.setQuantity(10); + + // act & assert + assertDoesNotThrow(() -> inventoryFacade.restockWine(testProductDTO)); + verify(inventoryService).restockWine(testProductDTO.getCode(), testProductDTO.getQuantity()); + } + + @Test + void shouldCreateTransactionSuccessfully() { + // arrange + TransactionDTO testTransactionDTO = new TransactionDTO(); + Transaction testTransaction = new Transaction(); + when(mapper.mapTransactionDtoToTransaction(testTransactionDTO)).thenReturn(testTransaction); + + // act & assert + assertDoesNotThrow(() -> inventoryFacade.createTransaction(testTransactionDTO)); + verify(transactionService).createTransaction(testTransaction); + } + + @Test + void shouldReturnNullWhenNoWineWithGivenCodeExists() { + // arrange + when(productService.getProductByCode(anyString())).thenReturn(null); + + // act + ProductDTO result = inventoryFacade.getWineByCode("non-existent-code"); + + // assert + assertNull(result); + } + + @Test + void shouldReturnWineWhenWineWithGivenCodeExists() { + // arrange + Product testProduct = new Product(); + ProductDTO testProductDTO = new ProductDTO(); + when(productService.getProductByCode(anyString())).thenReturn(testProduct); + when(mapper.mapProductToDTO(testProduct)).thenReturn(testProductDTO); - ProductDTO result = inventoryFacade.getWineByCode("test-code"); + // act + ProductDTO result = inventoryFacade.getWineByCode("existent-code"); + // assert assertEquals(testProductDTO, result); } @Test - void getGrapeList() { - when(grapeService.getGrapeList(0,10)).thenReturn(List.of(testGrape)); + void shouldReturnEmptyListWhenNoGrapesAvailable() { + // arrange + when(grapeService.getGrapeList(0, 10)).thenReturn(List.of()); + + // act + List<GrapeDTO> result = inventoryFacade.getGrapeList(0, 10); + + // assert + assertTrue(result.isEmpty()); + } + + @Test + void shouldReturnGrapeListWhenGrapesAreAvailable() { + // arrange + Grape testGrape = new Grape(); + GrapeDTO testGrapeDTO = new GrapeDTO(); + when(grapeService.getGrapeList(0, 10)).thenReturn(List.of(testGrape)); + when(mapper.mapGrapeToDTO(testGrape)).thenReturn(testGrapeDTO); + + // act + List<GrapeDTO> result = inventoryFacade.getGrapeList(0, 10); + + // assert + assertFalse(result.isEmpty()); + assertEquals(testGrapeDTO, result.getFirst()); + } + + @Test + void shouldReturnNullWhenNoGrapeWithGivenCodeExists() { + // arrange + when(grapeService.getGrapeByCode(anyString())).thenReturn(null); - List<GrapeDTO> result = inventoryFacade.getGrapeList(0,10); + // act + GrapeDTO result = inventoryFacade.getGrapeByCode("non-existent-code"); - assertEquals(List.of(testGrapeDTO), result); + // assert + assertNull(result); } @Test - void getGrapeByCode() { - when(grapeService.getGrapeByCode("test-code")).thenReturn(testGrape); + void shouldReturnGrapeWhenGrapeWithGivenCodeExists() { + // arrange + Grape testGrape = new Grape(); + GrapeDTO testGrapeDTO = new GrapeDTO(); + when(grapeService.getGrapeByCode(anyString())).thenReturn(testGrape); + when(mapper.mapGrapeToDTO(testGrape)).thenReturn(testGrapeDTO); - GrapeDTO result = inventoryFacade.getGrapeByCode("test-code"); + // act + GrapeDTO result = inventoryFacade.getGrapeByCode("existent-code"); + // assert assertEquals(testGrapeDTO, result); } @Test - void getIngredientByName() { - when(ingredientService.getIngredientByName("test-name")).thenReturn(testIngredient); + void shouldThrowExceptionWhenRestockingNonExistentGrape() throws GrapeDoesNotExistException { + // arrange + Grape testGrape = new Grape(); + GrapeDTO testGrapeDTO = new GrapeDTO(); + testGrapeDTO.setCode("non-existent-code"); + when(mapper.mapGrapeDTOToGrape(testGrapeDTO)).thenReturn(testGrape); + doThrow(GrapeDoesNotExistException.class).when(grapeService).restockGrape(testGrape); - IngredientDTO result = inventoryFacade.getIngredientByName("test-name"); + // act & assert + assertThrows(GrapeDoesNotExistException.class, () -> inventoryFacade.restockGrape(testGrapeDTO)); + } + @Test + void shouldRestockGrapeSuccessfullyWhenGrapeExists() throws GrapeDoesNotExistException { + // arrange + GrapeDTO testGrapeDTO = new GrapeDTO(); + testGrapeDTO.setCode("existent-code"); + testGrapeDTO.setQuantity(10); + + // act & assert + assertDoesNotThrow(() -> inventoryFacade.restockGrape(testGrapeDTO)); + verify(grapeService).restockGrape(mapper.mapGrapeDTOToGrape(testGrapeDTO)); + } + + @Test + void shouldReturnNullWhenNoIngredientWithGivenNameExists() { + // arrange + when(ingredientService.getIngredientByName(anyString())).thenReturn(null); + + // act + IngredientDTO result = inventoryFacade.getIngredientByName("non-existent-name"); + + // assert + assertNull(result); + } + + @Test + void shouldReturnIngredientWhenIngredientWithGivenNameExists() { + // arrange + Ingredient testIngredient = new Ingredient(); + IngredientDTO testIngredientDTO = new IngredientDTO(); + when(ingredientService.getIngredientByName(anyString())).thenReturn(testIngredient); + when(mapper.mapIngredientToDTO(testIngredient)).thenReturn(testIngredientDTO); + + // act + IngredientDTO result = inventoryFacade.getIngredientByName("existent-name"); + + // assert assertEquals(testIngredientDTO, result); } @Test - void getIngredientList() { - when(ingredientService.getIngredientList(0,10)).thenReturn(List.of(testIngredient)); + void shouldReturnEmptyListWhenNoIngredientsAvailable() { + // arrange + when(ingredientService.getIngredientList(0, 10)).thenReturn(List.of()); + + // act + List<IngredientDTO> result = inventoryFacade.getIngredientList(0, 10); + + // assert + assertTrue(result.isEmpty()); + } - List<IngredientDTO> result = inventoryFacade.getIngredientList(0,10); + @Test + void shouldReturnIngredientListWhenIngredientsAreAvailable() { + // arrange + Ingredient testIngredient = new Ingredient(); + IngredientDTO testIngredientDTO = new IngredientDTO(); + when(ingredientService.getIngredientList(0, 10)).thenReturn(List.of(testIngredient)); + when(mapper.mapIngredientToDTO(testIngredient)).thenReturn(testIngredientDTO); + + // act + List<IngredientDTO> result = inventoryFacade.getIngredientList(0, 10); + + // assert + assertFalse(result.isEmpty()); + assertEquals(testIngredientDTO, result.getFirst()); + } + + @Test + void shouldRestockIngredientSuccessfullyWhenIngredientExists() { + // arrange + IngredientDTO testIngredientDTO = new IngredientDTO(); + testIngredientDTO.setName("existent-name"); + testIngredientDTO.setQuantity(10); - assertEquals(List.of(testIngredientDTO), result); + // act & assert + assertDoesNotThrow(() -> inventoryFacade.restockIngredient(testIngredientDTO)); + verify(ingredientService).restockIngredient(mapper.mapIngredientDTOToIngredient(testIngredientDTO)); } -} \ No newline at end of file +} diff --git a/inventory-management/src/test/java/cz/muni/fi/pa165/service/IngredientServiceTest.java b/inventory-management/src/test/java/cz/muni/fi/pa165/service/IngredientServiceTest.java index c3997b89e9efe281c4da25d0485b24f2186b9384..0a29e7a7f32b9549eb70bf6e737d75dfcd19570d 100644 --- a/inventory-management/src/test/java/cz/muni/fi/pa165/service/IngredientServiceTest.java +++ b/inventory-management/src/test/java/cz/muni/fi/pa165/service/IngredientServiceTest.java @@ -1,6 +1,5 @@ package cz.muni.fi.pa165.service; -import cz.muni.fi.pa165.model.Grape; import cz.muni.fi.pa165.model.Ingredient; import cz.muni.fi.pa165.repository.IngredientRepository; import org.junit.jupiter.api.BeforeEach; @@ -15,7 +14,7 @@ import org.springframework.data.domain.Pageable; import java.util.List; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; class IngredientServiceTest { diff --git a/inventory-management/src/test/java/cz/muni/fi/pa165/service/ProductServiceTest.java b/inventory-management/src/test/java/cz/muni/fi/pa165/service/ProductServiceTest.java index f5c98926696ba3f38fb8906c8dee88c48c82c629..0074d8bd74919027cc7fb68203d9561b624cff6f 100644 --- a/inventory-management/src/test/java/cz/muni/fi/pa165/service/ProductServiceTest.java +++ b/inventory-management/src/test/java/cz/muni/fi/pa165/service/ProductServiceTest.java @@ -1,7 +1,6 @@ package cz.muni.fi.pa165.service; import cz.muni.fi.pa165.exceptions.ProductAlreadyExistsException; -import cz.muni.fi.pa165.model.Ingredient; import cz.muni.fi.pa165.model.Product; import cz.muni.fi.pa165.repository.ProductRepository; import org.junit.jupiter.api.BeforeEach;