Error handling, GET receipe

This commit is contained in:
Meutel 2023-10-23 19:00:33 +02:00
parent f5efa35c3d
commit deb36f05e3
9 changed files with 140 additions and 39 deletions

View File

@ -1,19 +1,16 @@
package net.meutel.recettes.api.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;
import net.meutel.recettes.api.ReceipeApi;
import net.meutel.recettes.api.ReceipesApi;
import net.meutel.recettes.api.model.Receipe;
import net.meutel.recettes.api.service.ReceipeService;
@RestController
public class ReceipeController implements ReceipeApi, ReceipesApi {
public class ReceipeController implements ReceipesApi {
private final ReceipeService service;
@ -21,14 +18,14 @@ public class ReceipeController implements ReceipeApi, ReceipesApi {
this.service = service;
}
@Override
public Optional<NativeWebRequest> getRequest() {
return ReceipeApi.super.getRequest();
}
@Override
public ResponseEntity<List<Receipe>> findReceipes() {
return ResponseEntity.ok(service.findReceipes());
}
@Override
public ResponseEntity<Receipe> getReceipeById(String receipeId) {
return ResponseEntity.ok(service.getReceipeById(receipeId));
}
}

View File

@ -0,0 +1,17 @@
package net.meutel.recettes.api.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ProblemDetail;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ItemNotFoundException.class)
ProblemDetail handleBookmarkNotFoundException(ItemNotFoundException e) {
return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
}
}

View File

@ -0,0 +1,9 @@
package net.meutel.recettes.api.exception;
public class ItemNotFoundException extends RuntimeException {
public ItemNotFoundException(String itemName, Object id) {
super(itemName + " not found with id " + id);
}
}

View File

@ -6,7 +6,7 @@ import net.meutel.recettes.api.entity.ReceipeEntity;
import net.meutel.recettes.api.model.Receipe;
@Mapper(componentModel = "spring")
public interface ReceipeMapper {
public interface ReceipeFullMapper {
Receipe fromEntity(ReceipeEntity entity);

View File

@ -0,0 +1,17 @@
package net.meutel.recettes.api.mapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import net.meutel.recettes.api.entity.ReceipeEntity;
import net.meutel.recettes.api.model.Receipe;
@Mapper(componentModel = "spring")
public interface ReceipeSimplifiedMapper {
@Mapping(target = "receipeYield", ignore = true)
Receipe fromEntity(ReceipeEntity entity);
ReceipeEntity toEntity(Receipe model);
}

View File

@ -2,6 +2,9 @@ package net.meutel.recettes.api.service;
import java.util.List;
import org.springframework.lang.NonNull;
import net.meutel.recettes.api.exception.ItemNotFoundException;
import net.meutel.recettes.api.model.Receipe;
public interface ReceipeService {
@ -10,4 +13,9 @@ public interface ReceipeService {
return List.of();
}
@NonNull
default Receipe getReceipeById(String id) {
throw new ItemNotFoundException("Receipe", id);
}
}

View File

@ -5,7 +5,8 @@ import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import net.meutel.recettes.api.mapper.ReceipeMapper;
import net.meutel.recettes.api.exception.ItemNotFoundException;
import net.meutel.recettes.api.mapper.ReceipeSimplifiedMapper;
import net.meutel.recettes.api.model.Receipe;
import net.meutel.recettes.api.repository.ReceipeRepository;
@ -13,9 +14,9 @@ import net.meutel.recettes.api.repository.ReceipeRepository;
public class ReceipeServiceImpl implements ReceipeService {
private final ReceipeRepository repo;
private final ReceipeMapper mapper;
private final ReceipeSimplifiedMapper mapper;
public ReceipeServiceImpl(ReceipeRepository repo, ReceipeMapper mapper) {
public ReceipeServiceImpl(ReceipeRepository repo, ReceipeSimplifiedMapper mapper) {
this.repo = repo;
this.mapper = mapper;
}
@ -28,4 +29,11 @@ public class ReceipeServiceImpl implements ReceipeService {
.collect(Collectors.toList());
}
@Override
public Receipe getReceipeById(String id) {
return repo.findById(id)
.map(mapper::fromEntity)
.orElseThrow(() -> new ItemNotFoundException("Receipe", id));
}
}

View File

@ -16,42 +16,64 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import net.meutel.recettes.api.exception.ItemNotFoundException;
import net.meutel.recettes.api.model.Receipe;
import net.meutel.recettes.api.service.ReceipeService;
@SpringBootTest
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class ReceipeControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private MockMvc mockMvc;
@MockBean
private ReceipeService service;
@MockBean
private ReceipeService service;
@Test
public void findReceipes_none_empty() throws Exception {
this.mockMvc.perform(get("/receipes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$").isEmpty());
public void getReceipeById_ItemNotFound_404() throws Exception {
when(service.getReceipeById("TEST"))
.thenThrow(new ItemNotFoundException("Receipe", "TEST"));
this.mockMvc.perform(get("/receipes/TEST"))
.andExpect(status().isNotFound());
}
@Test
public void findReceipes_exists_list() throws Exception {
Receipe r1 = new Receipe()
.name("pates carbo");
Receipe r2 = new Receipe()
.name("soupe a l'oignon");
when(service.findReceipes())
.thenReturn(List.of(r1, r2));
@Test
public void getReceipeById_exixts_success() throws Exception {
Receipe r1 = new Receipe()
.name("pates carbo");
when(service.getReceipeById("TEST"))
.thenReturn(r1);
this.mockMvc.perform(get("/receipes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$.[*].name").exists())
.andExpect(jsonPath("$.[0].name", equalTo("pates carbo")))
.andExpect(jsonPath("$.[*].description").doesNotExist());
}
this.mockMvc.perform(get("/receipes/TEST"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", equalTo("pates carbo")));
}
@Test
public void findReceipes_none_empty() throws Exception {
this.mockMvc.perform(get("/receipes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$").isEmpty());
}
@Test
public void findReceipes_exists_list() throws Exception {
Receipe r1 = new Receipe()
.name("pates carbo");
Receipe r2 = new Receipe()
.name("soupe a l'oignon");
when(service.findReceipes())
.thenReturn(List.of(r1, r2));
this.mockMvc.perform(get("/receipes"))
.andExpect(status().isOk())
.andExpect(jsonPath("$").isArray())
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$.[*].name").exists())
.andExpect(jsonPath("$.[0].name", equalTo("pates carbo")))
.andExpect(jsonPath("$.[*].description").doesNotExist());
}
}

View File

@ -4,13 +4,16 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import net.meutel.recettes.api.entity.ReceipeEntity;
import net.meutel.recettes.api.exception.ItemNotFoundException;
import net.meutel.recettes.api.model.Receipe;
import net.meutel.recettes.api.repository.ReceipeRepository;
@ -23,6 +26,26 @@ public class ReceipeServiceImplTest {
@MockBean
ReceipeRepository repo;
@Test
void getReceipeById_noData_exception() {
Assertions.assertThrows(ItemNotFoundException.class, () -> tested.getReceipeById("TEST"));
}
@Test
void getReceipeById_exists_receipe() {
ReceipeEntity r1 = new ReceipeEntity();
r1.setName("pates carbo");
when(repo.findById("TEST"))
.thenReturn(Optional.of(r1));
var result = tested.getReceipeById("TEST");
assertThat(result)
.isNotNull()
.extracting(Receipe::getName)
.isEqualTo("pates carbo");
}
@Test
void findReceipes_noData_empty() {
var result = tested.findReceipes();