-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from vanderleik/PPI-10-Criar-ProductController
Ppi 10 criar product controller
- Loading branch information
Showing
10 changed files
with
288 additions
and
5 deletions.
There are no files selected for viewing
54 changes: 54 additions & 0 deletions
54
src/main/java/com/produtopedidoitens/api/adapters/web/controllers/ProductController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package com.produtopedidoitens.api.adapters.web.controllers; | ||
|
||
import com.produtopedidoitens.api.adapters.web.requests.ProductRequest; | ||
import com.produtopedidoitens.api.adapters.web.responses.ProductResponse; | ||
import com.produtopedidoitens.api.application.port.ProductInputPort; | ||
import jakarta.validation.Valid; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
@Slf4j | ||
@RequiredArgsConstructor | ||
@RequestMapping("/api/v1/products") | ||
@RestController | ||
public class ProductController { | ||
|
||
private final ProductInputPort productInputPort; | ||
|
||
@PostMapping | ||
public ResponseEntity<ProductResponse> create(@Valid @RequestBody ProductRequest productRequest) { | ||
log.info("create:: Recebendo requisição para criar um produto com os dados: {}", productRequest); | ||
return ResponseEntity.ok(productInputPort.create(productRequest)); | ||
} | ||
|
||
@GetMapping | ||
public ResponseEntity<List<ProductResponse>> listAll() { | ||
log.info("listAll:: Recebendo requisição para listar todos os produtos"); | ||
return ResponseEntity.ok(productInputPort.list()); | ||
} | ||
|
||
@GetMapping("/{id}") | ||
public ResponseEntity<ProductResponse> read(@PathVariable String id) { | ||
log.info("read:: Recebendo requisição para buscar um produto pelo id: {}", id); | ||
return ResponseEntity.ok(productInputPort.read(UUID.fromString(id))); | ||
} | ||
|
||
@PutMapping("/{id}") | ||
public ResponseEntity<ProductResponse> update(@PathVariable String id, @Valid @RequestBody ProductRequest productRequest) { | ||
log.info("update:: Recebendo requisição para atualizar um produto com os dados: {}", productRequest); | ||
return ResponseEntity.ok(productInputPort.update(UUID.fromString(id), productRequest)); | ||
} | ||
|
||
@DeleteMapping("/{id}") | ||
public ResponseEntity<Void> delete(@PathVariable String id) { | ||
log.info("delete:: Recebendo requisição para deletar um produto pelo id: {}", id); | ||
productInputPort.delete(UUID.fromString(id)); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
...m/produtopedidoitens/api/adapters/web/controllers/exceptions/ProductExceptionHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.produtopedidoitens.api.adapters.web.controllers.exceptions; | ||
|
||
import com.produtopedidoitens.api.adapters.web.responses.ErrorResponseDTO; | ||
import com.produtopedidoitens.api.application.exceptions.BadRequestException; | ||
import com.produtopedidoitens.api.application.exceptions.ProductNotFoundException; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class ProductExceptionHandler { | ||
|
||
@ExceptionHandler(BadRequestException.class) | ||
public ResponseEntity<ErrorResponseDTO> handleBadRequestException(BadRequestException e) { | ||
return ResponseEntity.badRequest().body(new ErrorResponseDTO(e.getMessage())); | ||
} | ||
|
||
@ExceptionHandler(ProductNotFoundException.class) | ||
public ResponseEntity<ErrorResponseDTO> handleProductNotFoundException(ProductNotFoundException e) { | ||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponseDTO(e.getMessage())); | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
src/main/java/com/produtopedidoitens/api/adapters/web/responses/ErrorResponseDTO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package com.produtopedidoitens.api.adapters.web.responses; | ||
|
||
public record ErrorResponseDTO( | ||
String message | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/main/resources/db/migration/V202407091908__create_product_table.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/main/resources/db/migration/V202407091914__create_order_table.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
src/main/resources/db/migration/V202407091920__create_order_item_table.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
195 changes: 195 additions & 0 deletions
195
src/test/java/com/produtopedidoitens/api/adapters/web/controllers/ProductControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
package com.produtopedidoitens.api.adapters.web.controllers; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import com.produtopedidoitens.api.adapters.web.requests.ProductRequest; | ||
import com.produtopedidoitens.api.adapters.web.responses.ProductResponse; | ||
import com.produtopedidoitens.api.application.domain.enums.EnumProductType; | ||
import com.produtopedidoitens.api.application.exceptions.BadRequestException; | ||
import com.produtopedidoitens.api.application.exceptions.ProductNotFoundException; | ||
import com.produtopedidoitens.api.application.port.ProductInputPort; | ||
import com.produtopedidoitens.api.utils.MessagesConstants; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | ||
import org.springframework.boot.test.mock.mockito.MockBean; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.test.web.servlet.MockMvc; | ||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; | ||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers; | ||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; | ||
import org.springframework.web.context.WebApplicationContext; | ||
|
||
import java.math.BigDecimal; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
import static org.mockito.Mockito.doThrow; | ||
import static org.mockito.Mockito.when; | ||
|
||
@WebMvcTest(controllers = ProductController.class) | ||
class ProductControllerTest { | ||
|
||
private final String URL = "/api/v1/products"; | ||
|
||
@Autowired | ||
private MockMvc mockMvc; | ||
@Autowired | ||
private ObjectMapper objectMapper; | ||
@Autowired | ||
private WebApplicationContext webApplicationContext; | ||
|
||
@MockBean | ||
private ProductInputPort productInputPort; | ||
|
||
private ProductRequest productRequest; | ||
private ProductResponse productResponse; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
productRequest = ProductRequest.builder() | ||
.productName("Product 1") | ||
.price("100.0") | ||
.type("Produto") | ||
.active("true") | ||
.build(); | ||
|
||
productResponse = ProductResponse.builder() | ||
.id(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b")) | ||
.productName("Product 1") | ||
.price(BigDecimal.valueOf(100.0)) | ||
.type(EnumProductType.PRODUCT) | ||
.active(true) | ||
.dthreg(LocalDateTime.now()) | ||
.dthalt(LocalDateTime.now()) | ||
.version(0L) | ||
.build(); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve criar um produto") | ||
void testCreate() throws Exception { | ||
when(productInputPort.create(productRequest)).thenReturn(productResponse); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.post(URL) | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.content(objectMapper.writeValueAsString(productRequest))) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(productResponse))); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve retornar um erro ao criar um produto") | ||
void testCreateError() throws Exception { | ||
when(productInputPort.create(productRequest)).thenThrow(new BadRequestException(MessagesConstants.ERROR_SAVE_PRODUCT)); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.post(URL) | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.content(objectMapper.writeValueAsString(productRequest))) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isBadRequest()) | ||
.andExpect(MockMvcResultMatchers.content().json("{\"message\":\"Erro ao salvar produto/serviço\"}")); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve listar todos os produtos") | ||
void testList() throws Exception { | ||
when(productInputPort.list()).thenReturn(List.of(productResponse)); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.get(URL) | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(List.of(productResponse)))); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve retornar um erro ao listar todos os produtos") | ||
void testListError() throws Exception { | ||
when(productInputPort.list()).thenThrow(new ProductNotFoundException(MessagesConstants.ERROR_PRODUCT_NOT_FOUND)); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.get(URL) | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isNotFound()) | ||
.andExpect(MockMvcResultMatchers.content().json("{\"message\":\"Nenhum produto/serviço encontrado\"}")); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve buscar um produto pelo id") | ||
void testRead() throws Exception { | ||
when(productInputPort.read(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b"))).thenReturn(productResponse); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.get(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(productResponse))); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve retornar um erro ao buscar um produto pelo id") | ||
void testReadError() throws Exception { | ||
when(productInputPort.read(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b"))) | ||
.thenThrow(new ProductNotFoundException(MessagesConstants.ERROR_PRODUCT_NOT_FOUND)); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.get(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isNotFound()) | ||
.andExpect(MockMvcResultMatchers.content().json("{\"message\":\"Nenhum produto/serviço encontrado\"}")); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve atualizar um produto") | ||
void testUpdate() throws Exception { | ||
when(productInputPort.update(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b"), productRequest)).thenReturn(productResponse); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.put(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.content(objectMapper.writeValueAsString(productRequest))) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isOk()) | ||
.andExpect(MockMvcResultMatchers.content().json(objectMapper.writeValueAsString(productResponse))); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve retornar um erro ao atualizar um produto") | ||
void testUpdateError() throws Exception { | ||
when(productInputPort.update(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b"), productRequest)) | ||
.thenThrow(new BadRequestException(MessagesConstants.ERROR_UPDATE_PRODUCT)); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.put(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON) | ||
.content(objectMapper.writeValueAsString(productRequest))) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isBadRequest()) | ||
.andExpect(MockMvcResultMatchers.content().json("{\"message\":\"Erro ao atualizar produto/serviço\"}")); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve deletar um produto") | ||
void testDelete() throws Exception { | ||
mockMvc.perform(MockMvcRequestBuilders.delete(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isNoContent()); | ||
} | ||
|
||
@Test | ||
@DisplayName("Deve retornar um erro ao deletar um produto") | ||
void testDeleteError() throws Exception { | ||
doThrow(new BadRequestException(MessagesConstants.ERROR_DELETE_PRODUCT)) | ||
.when(productInputPort).delete(UUID.fromString("f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b")); | ||
|
||
mockMvc.perform(MockMvcRequestBuilders.delete(URL + "/f7f6b1e3-4b7b-4b6b-8b7b-4b7b6b8b7b4b") | ||
.contentType(MediaType.APPLICATION_JSON)) | ||
.andDo(MockMvcResultHandlers.print()) | ||
.andExpect(MockMvcResultMatchers.status().isBadRequest()) | ||
.andExpect(MockMvcResultMatchers.content().json("{\"message\":\"Erro ao deletar produto/serviço\"}")); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.