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;