Final Modif
This commit is contained in:
parent
d66be27cfe
commit
3ea04efcc6
24 changed files with 5124 additions and 43 deletions
4473
log/avis_dev_log
Normal file
4473
log/avis_dev_log
Normal file
File diff suppressed because it is too large
Load diff
49
pom.xml
49
pom.xml
|
|
@ -81,22 +81,20 @@
|
|||
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||
<version>2.8.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId>
|
||||
<version>1.6.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.javafaker</groupId>
|
||||
<artifactId>javafaker</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
|
@ -109,7 +107,32 @@
|
|||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok-mapstruct-binding</artifactId>
|
||||
<version>0.2.0</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-processor</artifactId>
|
||||
<version>1.6.3</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -10,13 +10,7 @@ import java.time.LocalDate;
|
|||
public class AvisApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SpringApplication.run(AvisApplication.class, args);
|
||||
Joueur joueur = Joueur.builder()
|
||||
.pseudo("Joueur")
|
||||
.email("amaury.maizy@soprasteria.com")
|
||||
.dateDeNaissance(LocalDate.of(2000, 1, 1))
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
61
src/main/java/fr/clelia/avis/aop/LoggingAspect.java
Normal file
61
src/main/java/fr/clelia/avis/aop/LoggingAspect.java
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package fr.clelia.avis.aop;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@Aspect
|
||||
@AllArgsConstructor
|
||||
@Log4j2
|
||||
@Component
|
||||
public class LoggingAspect {
|
||||
|
||||
// Toutes les méthodes dans les packages énumérés
|
||||
/*
|
||||
@Pointcut("within(fr.clelia.avis.repository..*)"
|
||||
+ " || within(fr.clelia.avis.service..*)"
|
||||
+ " || within(fr.clelia.avis.initialisation..*)"
|
||||
+ " || within(fr.clelia.avis.controller..*)"
|
||||
+ " || within(fr.clelia.avis.controller.rest..*)")
|
||||
*/
|
||||
|
||||
// Toutes les méthodes de la classe
|
||||
// @Pointcut("within(fr.clelia.avis.controller.rest.JeuRestController)")
|
||||
|
||||
// Toutes les classes annotées @Service
|
||||
@Pointcut("@within(org.springframework.stereotype.Service)")
|
||||
|
||||
// Toutes les méthodes annotées @Transactional
|
||||
//@Pointcut("execution(@org.springframework.transaction.annotation.Transactional * *(..))")
|
||||
|
||||
// Toutes les méthodes annotées @Transactional dont le nom débute par i
|
||||
//@Pointcut("execution(@org.springframework.transaction.annotation.Transactional * i*(..))")
|
||||
|
||||
//@Pointcut("execution(@org.springframework.transaction.annotation.Transactional java.util.List i*(..))")
|
||||
public void avisPackagePointcut() {
|
||||
}
|
||||
|
||||
@Around("avisPackagePointcut()")
|
||||
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
|
||||
try {
|
||||
Object result = joinPoint.proceed();
|
||||
log.info("Invocation {} avec arguments {} : ", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
|
||||
System.out.println("Invocation : " + joinPoint.getSignature().getName() + "() argument[s] = "
|
||||
+ Arrays.toString(joinPoint.getArgs())
|
||||
+ " resultat = " + result);
|
||||
return result;
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Exception levée : {} dans {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName());
|
||||
System.err.println("Exception levée : " + e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonManagedReference;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
|
|
@ -26,7 +27,9 @@ public class Editeur {
|
|||
private Long id;
|
||||
|
||||
@Column(length = 100, unique = true)
|
||||
// Contrainte métier : le nom de l'éditeur ne peut pas être une chaîne vide
|
||||
@NotBlank(message="Merci de préciser le nom de l'éditeur")
|
||||
@Size(min=2, message="Le nom de l'éditeur doit comporter au moins {min} caractères")
|
||||
private String nom;
|
||||
|
||||
private String logo;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.clelia.avis.business;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.validation.constraints.Past;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
|
@ -13,6 +14,7 @@ import java.time.LocalDate;
|
|||
@Data
|
||||
public class Joueur extends Utilisateur {
|
||||
|
||||
@Past(message="Merci de préciser une date de naissance dans le passé")
|
||||
private LocalDate dateDeNaissance;
|
||||
|
||||
public Joueur(String pseudo, String email, String motDePasse, LocalDate dateDeNaissance) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
package fr.clelia.avis.controller.rest;
|
||||
|
||||
import fr.clelia.avis.util.ReponseApi;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class AvisRestControllerAdvice {
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public ReponseApi<String> traiterDonneesInvalides(ConstraintViolationException e){
|
||||
//return new ReponseApi<>(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getMessage(), null);
|
||||
return new ReponseApi<>(String.valueOf(HttpStatus.BAD_REQUEST.value()), e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).toList().toString(), null);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +1,21 @@
|
|||
package fr.clelia.avis.controller.rest;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
import fr.clelia.avis.exception.EditeurInexistantException;
|
||||
import fr.clelia.avis.mapper.EditeurMapper;
|
||||
import fr.clelia.avis.service.EditeurService;
|
||||
import fr.clelia.avis.util.ReponseApi;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
@AllArgsConstructor
|
||||
|
|
@ -18,6 +24,7 @@ import java.util.List;
|
|||
public class EditeurRestController {
|
||||
|
||||
private final EditeurService editeurService;
|
||||
private final EditeurMapper editeurMapper;
|
||||
|
||||
@GetMapping("")
|
||||
@Operation(summary="Récupère tous les éditeurs")
|
||||
|
|
@ -25,25 +32,44 @@ public class EditeurRestController {
|
|||
return editeurService.recupererEditeurs();
|
||||
}
|
||||
|
||||
// @GetMapping("/{id}")
|
||||
// @Operation(summary="Récupère un éditeur par son id")
|
||||
// public EditeurDto getEditeur(@PathVariable Long id) {
|
||||
// return editeurMapper.toDto(editeurService.recupererEditeur(id));
|
||||
// }
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@Operation(summary="Récupère un éditeur par son id")
|
||||
public Editeur getEditeur(@PathVariable Long id) {
|
||||
return editeurService.recupererEditeur(id);
|
||||
public ResponseEntity<EditeurDto> getEditeur(@PathVariable Long id) {
|
||||
return ResponseEntity.ok(editeurMapper.toDto(editeurService.recupererEditeur(id)));
|
||||
}
|
||||
|
||||
@PostMapping("")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@Operation(summary = "Ajoute un nouvel éditeur")
|
||||
public Editeur postEditeur(@RequestBody Editeur editeur) {
|
||||
return editeurService.ajouterEditeur(editeur);
|
||||
// https://sonarsource.atlassian.net/browse/RSPEC-4684
|
||||
//public Editeur postEditeur(@RequestBody Editeur editeur) {
|
||||
public ResponseEntity<EditeurDto> postEditeur(@RequestBody EditeurDto editeurDto) throws URISyntaxException {
|
||||
//return editeurMapper.toDto(editeurService.ajouterEditeur(editeurMapper.toEntity(editeurDto)));
|
||||
EditeurDto editeurDtoAjoute = editeurMapper.toDto(editeurService.ajouterEditeur(editeurMapper.toEntity(editeurDto)));
|
||||
return ResponseEntity.created(new URI("/api/editeurs/" + editeurDtoAjoute.id()))
|
||||
.body(editeurDtoAjoute);
|
||||
}
|
||||
|
||||
// TODO comprendre comment les plateformes sur le findAll
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "Supprime un éditeur")
|
||||
@ResponseStatus(HttpStatus.NO_CONTENT)
|
||||
public void deleteEditeur(@PathVariable Long id) {
|
||||
editeurService.supprimerEditeur(id);
|
||||
}
|
||||
|
||||
@ExceptionHandler(EditeurInexistantException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public ReponseApi<String> traiterEditeurInexistantException(EditeurInexistantException e){
|
||||
//return e.getMessage();
|
||||
return new ReponseApi<>(String.valueOf(HttpStatus.NOT_FOUND.value()), e.getMessage(), null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
15
src/main/java/fr/clelia/avis/dto/EditeurDto.java
Normal file
15
src/main/java/fr/clelia/avis/dto/EditeurDto.java
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package fr.clelia.avis.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO for {@link fr.clelia.avis.business.Editeur}
|
||||
*/
|
||||
public record EditeurDto(Long id,
|
||||
@Size(message = "Le nom de l'éditeur doit comporter au moins {min} caractères", min = 2) @NotBlank(message = "Merci de préciser le nom de l'éditeur") String nom,
|
||||
String logo, List<JeuDto> jeux) implements Serializable {
|
||||
}
|
||||
12
src/main/java/fr/clelia/avis/dto/JeuDto.java
Normal file
12
src/main/java/fr/clelia/avis/dto/JeuDto.java
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package fr.clelia.avis.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO for {@link fr.clelia.avis.business.Jeu}
|
||||
*/
|
||||
public record JeuDto(Long id, String nom, EditeurDto editeur, LocalDate dateDeSortie,
|
||||
boolean possedeImage, List<PlateformeDto> plateformeDtoList) implements Serializable {
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
package fr.clelia.avis.dto;
|
||||
|
||||
public record NbJoueursParAnneeDeNaissance(int annee, long nbJoueurs) {
|
||||
}
|
||||
6
src/main/java/fr/clelia/avis/dto/PlateformeDto.java
Normal file
6
src/main/java/fr/clelia/avis/dto/PlateformeDto.java
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
package fr.clelia.avis.dto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record PlateformeDto(Long id, String nom, List<JeuDto> jeux) {
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import fr.clelia.avis.repository.*;
|
|||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
|
@ -16,6 +17,7 @@ import java.util.Random;
|
|||
@Component // Spring va instancier cette classe
|
||||
// et placer cette instance dans son conteneur IoC
|
||||
@AllArgsConstructor
|
||||
@Profile({"dev", "prod"})
|
||||
public class AjoutDonneesInitiales {
|
||||
|
||||
// Dépendances
|
||||
|
|
@ -46,6 +48,7 @@ public class AjoutDonneesInitiales {
|
|||
.forEach(System.out::println);
|
||||
joueurRepository.findJoueursTrentenaires().forEach(System.out::println);
|
||||
jeuRepository.findJeuxByPlateforme(plateformeRepository.findAll().get(0)).forEach(System.out::println);
|
||||
joueurRepository.findNbJoueursParAnneeDeNaissance().forEach(System.out::println);
|
||||
}
|
||||
|
||||
private void ajouterEditeurs() {
|
||||
|
|
|
|||
23
src/main/java/fr/clelia/avis/mapper/EditeurMapper.java
Normal file
23
src/main/java/fr/clelia/avis/mapper/EditeurMapper.java
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package fr.clelia.avis.mapper;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
import org.mapstruct.*;
|
||||
|
||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING, uses = JeuMapper.class)
|
||||
public interface EditeurMapper {
|
||||
Editeur toEntity(EditeurDto editeurDto);
|
||||
|
||||
@AfterMapping
|
||||
default void linkJeux(@MappingTarget Editeur editeur) {
|
||||
if (editeur.getJeux()==null) {
|
||||
return;
|
||||
}
|
||||
editeur.getJeux().forEach(jeux -> jeux.setEditeur(editeur));
|
||||
}
|
||||
|
||||
EditeurDto toDto(Editeur editeur);
|
||||
|
||||
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||
Editeur partialUpdate(EditeurDto editeurDto, @MappingTarget Editeur editeur);
|
||||
}
|
||||
16
src/main/java/fr/clelia/avis/mapper/JeuMapper.java
Normal file
16
src/main/java/fr/clelia/avis/mapper/JeuMapper.java
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
package fr.clelia.avis.mapper;
|
||||
|
||||
import fr.clelia.avis.business.Jeu;
|
||||
import fr.clelia.avis.dto.JeuDto;
|
||||
import org.mapstruct.*;
|
||||
|
||||
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = MappingConstants.ComponentModel.SPRING)
|
||||
public interface JeuMapper {
|
||||
Jeu toEntity(JeuDto jeuDto);
|
||||
|
||||
@Mapping(target="editeur", ignore = true)
|
||||
JeuDto toDto(Jeu jeu);
|
||||
|
||||
@BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
|
||||
Jeu partialUpdate(JeuDto jeuDto, @MappingTarget Jeu jeu);
|
||||
}
|
||||
|
|
@ -1,13 +1,21 @@
|
|||
package fr.clelia.avis.repository;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.business.Jeu;
|
||||
import fr.clelia.avis.business.Plateforme;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
import org.springframework.data.rest.core.annotation.RestResource;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@RepositoryRestResource
|
||||
|
||||
public interface JeuRepository extends JpaRepository<Jeu, Long> {
|
||||
|
||||
|
|
@ -29,4 +37,45 @@ public interface JeuRepository extends JpaRepository<Jeu, Long> {
|
|||
List<Jeu> findJeuxByNomPlateforme(@Param("nomPlateforme") String nomPlateforme);
|
||||
|
||||
List<Jeu> findByPlateformesNom(String nom);
|
||||
|
||||
Jeu findFirstByNom(String nom);
|
||||
|
||||
List<Jeu> findByEditeur(Editeur editeur);
|
||||
|
||||
// Navigabilité
|
||||
List<Jeu> findByEditeurNom(String nom);
|
||||
|
||||
List<Jeu> findTop5ByEditeurOrderByDateDeSortieDesc(Editeur editeur);
|
||||
|
||||
List<Jeu> findByNomLike(String nom);
|
||||
|
||||
List<Jeu> findByNomLikeAndDateDeSortieBetween(String nom, LocalDate dateDebut, LocalDate dateFin);
|
||||
|
||||
List<Jeu> findByEditeurAndNomLikeAndDateDeSortieBetween(Editeur editeur, String nom, LocalDate dateDebut, LocalDate dateFin);
|
||||
|
||||
/**
|
||||
* Cette méthode renvoie les jeux disponibles sur la plateforme donnée en paramètre
|
||||
*
|
||||
* @param plateforme
|
||||
* @return
|
||||
*/
|
||||
List<Jeu> findAllByPlateformesContaining(Plateforme plateforme);
|
||||
|
||||
List<Jeu> findByDateDeSortieBetweenAndEditeur_NomContainsIgnoreCase(LocalDate dateSortieStart, LocalDate dateSortieEnd, String nom);
|
||||
|
||||
boolean existsByNom(String nom);
|
||||
|
||||
long countByEditeur(Editeur editeur);
|
||||
|
||||
long countByEditeurNom(String nom);
|
||||
|
||||
@Transactional
|
||||
long deleteByEditeur(Editeur editeur);
|
||||
|
||||
List<Jeu> findByPlateformes(Plateforme plateforme);
|
||||
|
||||
Optional<Jeu> findByNomIgnoreCase(String nom);
|
||||
|
||||
@RestResource(exported = false)
|
||||
void delete(Jeu jeu);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.clelia.avis.repository;
|
||||
|
||||
import fr.clelia.avis.business.Joueur;
|
||||
import fr.clelia.avis.dto.NbJoueursParAnneeDeNaissance;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
|
|
@ -24,4 +25,14 @@ public interface JoueurRepository extends JpaRepository<Joueur, Long> {
|
|||
AND j.dateDeNaissance > current_date() - 40 year
|
||||
""")
|
||||
List<Joueur> findJoueursTrentenaires();
|
||||
|
||||
// SELECT new : projection
|
||||
// après le new on précisera le constructeur d'un record ou d'une classe
|
||||
@Query("""
|
||||
SELECT new fr.clelia.avis.dto.NbJoueursParAnneeDeNaissance(year(dateDeNaissance), count(*))
|
||||
FROM Joueur
|
||||
GROUP BY dateDeNaissance
|
||||
""")
|
||||
List<NbJoueursParAnneeDeNaissance> findNbJoueursParAnneeDeNaissance();
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package fr.clelia.avis.service;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -13,4 +14,10 @@ public interface EditeurService {
|
|||
Editeur recupererEditeur(Long id);
|
||||
|
||||
Editeur ajouterEditeur(Editeur editeur);
|
||||
|
||||
EditeurDto mettreAJourEditeurPartiellement(Long id, EditeurDto editeurDto);
|
||||
|
||||
EditeurDto mettreAJourEditeur(Long id, EditeurDto editeurDto);
|
||||
|
||||
void supprimerEditeur(Long id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
package fr.clelia.avis.service.impl;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
import fr.clelia.avis.exception.EditeurInexistantException;
|
||||
import fr.clelia.avis.mapper.EditeurMapper;
|
||||
import fr.clelia.avis.repository.EditeurRepository;
|
||||
import fr.clelia.avis.service.EditeurService;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
|
@ -12,16 +15,18 @@ import java.util.List;
|
|||
//@Component
|
||||
@Service
|
||||
@Transactional
|
||||
@AllArgsConstructor
|
||||
public class EditeurServiceImpl implements EditeurService {
|
||||
|
||||
private EditeurRepository editeurRepository;
|
||||
private final EditeurRepository editeurRepository;
|
||||
private final EditeurMapper editeurMapper;
|
||||
|
||||
// Ce constructeur va faire déduire à Spring
|
||||
// qu'il doit d'abord instancier la repo
|
||||
// avant d'instancier le service
|
||||
public EditeurServiceImpl(EditeurRepository editeurRepository) {
|
||||
/*
|
||||
public EditeurServiceImpl(EditeurRepository editeurRepository, EditeurMapper editeurMapper) {
|
||||
this.editeurRepository = editeurRepository;
|
||||
this.editeurMapper = editeurMapper;
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public List<Editeur> recupererEditeurs() {
|
||||
|
|
@ -43,4 +48,24 @@ public class EditeurServiceImpl implements EditeurService {
|
|||
public Editeur ajouterEditeur(Editeur editeur) {
|
||||
return editeurRepository.save(editeur);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditeurDto mettreAJourEditeurPartiellement(Long id, EditeurDto editeurDto) {
|
||||
Editeur editeur = recupererEditeur(id);
|
||||
editeur = editeurRepository.save(editeurMapper.partialUpdate(editeurDto, editeur));
|
||||
return editeurMapper.toDto(editeur);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditeurDto mettreAJourEditeur(Long id, EditeurDto editeurDto) {
|
||||
Editeur editeurMisAJour = editeurMapper.toEntity(editeurDto);
|
||||
editeurMisAJour.setId(id);
|
||||
editeurRepository.save(editeurMisAJour);
|
||||
return editeurMapper.toDto(editeurMisAJour);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void supprimerEditeur(Long id) {
|
||||
editeurRepository.delete(recupererEditeur(id));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,18 @@ spring.jpa.generate-ddl=true
|
|||
spring.data.rest.detection-strategy=annotated
|
||||
spring.data.rest.base-path=/api-autogeneree/
|
||||
|
||||
spring.datasource.url=jdbc:h2:mem:avis
|
||||
|
||||
logging.level.org.hibernate.orm.jdbc.bind=trace
|
||||
|
||||
spring.profiles.active=dev
|
||||
|
||||
#---
|
||||
spring.config.activate.on-profile=dev
|
||||
logging.level.root=INFO
|
||||
logging.level.org.springframework=DEBUG
|
||||
logging.file.name=log/avis_dev_log
|
||||
logging.pattern.console= %d %p %c{1.} [%t] %m%n
|
||||
spring.jpa.show-sql=true
|
||||
management.endpoints.web.base-path=/
|
||||
management.endpoints.web.exposure.include=beans,health,env,configprops
|
||||
|
|
@ -12,4 +24,10 @@ management.endpoint.health.group.custom.show-components=always
|
|||
management.endpoint.health.group.custom.show-details=always
|
||||
management.endpoint.env.show-values=always
|
||||
management.endpoint.configprops.show-values=always
|
||||
spring.datasource.url=jdbc:h2:mem:avis
|
||||
|
||||
#---
|
||||
spring.config.activate.on-profile=prod
|
||||
logging.level.root=WARN
|
||||
logging.level.org.springframework=WARN
|
||||
logging.file.name=log/avis_prod_log
|
||||
logging.pattern.console= %d %p %c{1.} [%t] %m%n
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
package fr.clelia.avis.controller.rest;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.javafaker.Faker;
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
import fr.clelia.avis.service.EditeurService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
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.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
class EditeurRestControllerITest {
|
||||
|
||||
// cet objet imite ce que fait Postwoman, Postman, Insomnia, Bruno, Swagger ou le front
|
||||
// Angular
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Autowired
|
||||
private EditeurService editeurService;
|
||||
|
||||
private Faker faker = new Faker(Locale.FRENCH);
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
List<Editeur> editeurs = editeurService.recupererEditeurs();
|
||||
editeurs.forEach(editeur -> { editeurService.supprimerEditeur(editeur.getId()); });
|
||||
}
|
||||
|
||||
//@Test
|
||||
@RepeatedTest(10)
|
||||
void testerPostEditeur() throws Exception {
|
||||
// Arrange
|
||||
String nomEditeur = faker.company().name();
|
||||
String nomLogo = faker.company().logo();
|
||||
EditeurDto editeurDto = new EditeurDto(null, nomEditeur, nomLogo, new ArrayList<>());
|
||||
|
||||
MockHttpServletRequestBuilder requestBuilder = post("/api/editeurs")
|
||||
// On place dans le corps de la requête la version JSON de notre éditeur DTO
|
||||
.content(objectMapper.writeValueAsString(editeurDto))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON);
|
||||
|
||||
// Act
|
||||
mockMvc.perform(requestBuilder)
|
||||
// Assert
|
||||
// On vérifie que le code retour est bien 201 (created)
|
||||
.andExpect(status().isCreated())
|
||||
// On vérifie les données présentes dans le corps de la réponse
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.nom").value(nomEditeur))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.logo").value(nomLogo))
|
||||
// On affiche en console tout ce qui a été envoyé et reçu
|
||||
.andDo(MockMvcResultHandlers.print());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetEditeur() throws Exception {
|
||||
// Arrange
|
||||
String editeur = "test";
|
||||
String logo="logo";
|
||||
Editeur e = editeurService.ajouterEditeur(new Editeur(editeur, logo));
|
||||
|
||||
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/editeurs/{id}", e.getId());
|
||||
|
||||
// Act
|
||||
mockMvc.perform(requestBuilder)
|
||||
// Assert
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.nom").value(e.getNom()))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.logo").value(e.getLogo()))
|
||||
.andExpect(status().is2xxSuccessful())
|
||||
.andDo(MockMvcResultHandlers.print());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testerPostEditeurNomVide() throws Exception {
|
||||
// Arrange
|
||||
String nomEditeur = "";
|
||||
String nomLogo = "logo";
|
||||
Editeur editeur = new Editeur(nomEditeur, nomLogo);
|
||||
|
||||
MockHttpServletRequestBuilder requestBuilder = post("/api/editeurs")
|
||||
// On place dans le corps de la requête la version JSON de notre éditeur
|
||||
.content(objectMapper.writeValueAsString(editeur))
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON);
|
||||
|
||||
// Act
|
||||
mockMvc.perform(requestBuilder)
|
||||
// Assert
|
||||
// On vérifie que le code retour est bien 400 (bad request)
|
||||
.andExpect(status().isBadRequest())
|
||||
// On affiche en console tout ce qui a été envoyé et reçu
|
||||
.andDo(MockMvcResultHandlers.print());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetEditeurs() throws Exception {
|
||||
String nomEditeur1 = "testEditeur1";
|
||||
String logoEditeur1 = "logoEditeur1";
|
||||
String nomEditeur2 = "testEditeur2";
|
||||
String logoEditeur2 = "logoEditeur1";
|
||||
Editeur editeur1 = new Editeur(nomEditeur1, logoEditeur1);
|
||||
Editeur editeur2 = new Editeur(nomEditeur2, logoEditeur2);
|
||||
editeurService.ajouterEditeur(editeur1);
|
||||
editeurService.ajouterEditeur(editeur2);
|
||||
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.get("/api/editeurs");
|
||||
|
||||
mockMvc.perform(requestBuilder)
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[0].id").isNumber())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[0].nom").value(nomEditeur1))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[0].logo").value(logoEditeur1))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[1].id").isNumber())
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[1].nom").value(nomEditeur2))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$[1].logo").value(logoEditeur2))
|
||||
.andExpect(MockMvcResultMatchers.jsonPath("$.length()").value(2));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package fr.clelia.avis.repository;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@DataJpaTest
|
||||
public class EditeurRepositoryTest {
|
||||
|
||||
@Autowired
|
||||
private EditeurRepository editeurRepository;
|
||||
|
||||
@Test
|
||||
void testSaveEditeur() {
|
||||
// Arrange
|
||||
String nom = "test";
|
||||
String logo = "logo";
|
||||
Editeur editeur = new Editeur(nom, logo);
|
||||
|
||||
// Act
|
||||
Editeur editeurEnregistre = editeurRepository.save(editeur);
|
||||
|
||||
// Assert
|
||||
assertThat(editeurEnregistre.getNom()).isEqualTo(nom);
|
||||
assertThat(editeurEnregistre.getLogo()).isEqualTo(logo);
|
||||
}
|
||||
|
||||
// C'est plutôt intéressant pour tester des méthodes annotées @Query
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
package fr.clelia.avis.service.impl;
|
||||
|
||||
import fr.clelia.avis.business.Editeur;
|
||||
import fr.clelia.avis.dto.EditeurDto;
|
||||
import fr.clelia.avis.dto.JeuDto;
|
||||
import fr.clelia.avis.dto.PlateformeDto;
|
||||
import fr.clelia.avis.exception.EditeurInexistantException;
|
||||
import fr.clelia.avis.mapper.EditeurMapper;
|
||||
import fr.clelia.avis.repository.EditeurRepository;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
class EditeurServiceImplTest {
|
||||
@Mock
|
||||
EditeurRepository editeurRepository;
|
||||
@Mock
|
||||
EditeurMapper editeurMapper;
|
||||
@InjectMocks
|
||||
EditeurServiceImpl editeurServiceImpl;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecupererEditeurs() {
|
||||
when(editeurRepository.findAll()).thenReturn(List.of(new Editeur("nom", "logo")));
|
||||
|
||||
List<Editeur> result = editeurServiceImpl.recupererEditeurs();
|
||||
Assertions.assertEquals(List.of(new Editeur("nom", "logo")), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecupererEditeursAyantUnNomContenant() {
|
||||
String nomContenant = "contenant";
|
||||
when(editeurRepository.findByNomContainingIgnoreCase(anyString())).thenReturn(List.of(new Editeur(nomContenant, "logo")));
|
||||
|
||||
List<Editeur> result = editeurServiceImpl.recupererEditeursAyantUnNomContenant("nomRecherche");
|
||||
Assertions.assertEquals(List.of(new Editeur(nomContenant, "logo")), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAjouterEditeur() {
|
||||
// Arrange
|
||||
String nom = "nom";
|
||||
String logo = "logo";
|
||||
Editeur editeur = new Editeur(nom, logo);
|
||||
when(editeurRepository.save(any(Editeur.class))).thenReturn(editeur);
|
||||
|
||||
// Act
|
||||
Editeur result = editeurServiceImpl.ajouterEditeur(new Editeur(nom, logo));
|
||||
|
||||
// Assert
|
||||
Assertions.assertEquals(editeur, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRecupererEditeur() {
|
||||
// Arrange
|
||||
String nom = "nom";
|
||||
String logo = "logo";
|
||||
Editeur editeur = new Editeur(nom, logo);
|
||||
when(editeurRepository.findById(any(Long.class))).thenReturn(Optional.of(editeur));
|
||||
List<JeuDto> jeuxDto = new ArrayList<>();
|
||||
EditeurDto editeurDto = new EditeurDto(null, nom, logo, jeuxDto);
|
||||
when(editeurMapper.toDto(any(Editeur.class))).thenReturn(editeurDto);
|
||||
|
||||
// Act
|
||||
Editeur result = editeurServiceImpl.recupererEditeur(Long.valueOf(1));
|
||||
|
||||
// Assert
|
||||
Assertions.assertEquals(editeur, result);
|
||||
}
|
||||
|
||||
// TODO écrire les deux méthodes de test manquantes
|
||||
|
||||
@Test
|
||||
void testSupprimerEditeur() {
|
||||
// Arrange
|
||||
when(editeurRepository.findById(any(Long.class)))
|
||||
.thenReturn(Optional.of(new Editeur("nom", "logo")))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
// Act
|
||||
editeurServiceImpl.supprimerEditeur(Long.valueOf(1));
|
||||
|
||||
// Assert
|
||||
Assertions.assertThrows(EditeurInexistantException.class, () -> editeurServiceImpl.supprimerEditeur(Long.valueOf(1)));
|
||||
}
|
||||
}
|
||||
|
||||
//Generated with love by TestMe :) Please raise issues & feature requests at: https://weirddev.com/forum#!/testme
|
||||
13
src/test/resources/application.properties
Normal file
13
src/test/resources/application.properties
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
spring.application.name=avis
|
||||
|
||||
spring.jpa.generate-ddl=true
|
||||
|
||||
spring.data.rest.detection-strategy=annotated
|
||||
spring.data.rest.base-path=/api-autogeneree/
|
||||
|
||||
spring.jpa.show-sql=false
|
||||
|
||||
spring.datasource.url=jdbc:h2:mem:avis_test
|
||||
|
||||
logging.level.org.hibernate.orm.jdbc.bind=trace
|
||||
|
||||
Loading…
Add table
Reference in a new issue