diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..48ca5f4
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: weekly
+ - package-ecosystem: maven
+ directory: /
+ schedule:
+ interval: weekly
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..ed7caa2
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,21 @@
+name: ci
+on:
+ pull_request:
+ branches: [main]
+
+permissions:
+ contents: read
+
+jobs:
+ check:
+ name: check
+ runs-on: ubuntu-24.04
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
+ with:
+ distribution: temurin
+ java-version: '21'
+ cache: maven
+ - name: Compile and run the tests
+ run: sh ./mvnw -B verify
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
new file mode 100644
index 0000000..788e8b2
--- /dev/null
+++ b/.github/workflows/codeql.yml
@@ -0,0 +1,29 @@
+name: codeql
+on:
+ pull_request:
+ branches: [main]
+
+permissions:
+ contents: read
+
+jobs:
+ analyze:
+ name: codeql (${{ matrix.language }})
+ runs-on: ubuntu-24.04
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [java-kotlin, actions]
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
+ with:
+ languages: ${{ matrix.language }}
+ build-mode: none
+ - uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
+ with:
+ category: /language:${{ matrix.language }}
diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml
new file mode 100644
index 0000000..903a4fa
--- /dev/null
+++ b/.github/workflows/trivy.yml
@@ -0,0 +1,30 @@
+name: trivy
+on:
+ pull_request:
+ branches: [main]
+
+permissions:
+ contents: read
+
+jobs:
+ security:
+ name: security
+ runs-on: ubuntu-24.04
+ permissions:
+ contents: read
+ security-events: write
+ steps:
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ - uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
+ with:
+ scan-type: fs
+ format: sarif
+ output: trivy-results.sarif
+ exit-code: '1'
+ severity: CRITICAL,HIGH
+ ignore-unfixed: true
+ limit-severities-for-sarif: true
+ - uses: github/codeql-action/upload-sarif@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
+ if: always()
+ with:
+ sarif_file: trivy-results.sarif
diff --git a/README.md b/README.md
index 7d950d3..cb2a67e 100644
--- a/README.md
+++ b/README.md
@@ -12,6 +12,7 @@ Bienvenue dans **SWAPI**, une API Spring Boot conçue pour consommer et servir d
- [Endpoints](#endpoints)
- [Exemples d'utilisation](#exemples-dutilisation)
- [Tests](#tests)
+- [Qualité et CI](#qualité-et-ci)
- [Swagger UI](#swagger-ui)
- [Contributions](#contributions)
@@ -121,9 +122,23 @@ Réponse :
Le projet inclut des tests unitaires et d'intégration utilisant **Spring Boot Starter Test** et **Reactor Test** pour les flux réactifs. Pour exécuter les tests :
```bash
-mvn test
+sh ./mvnw test
```
+## Qualité et CI
+
+La commande `sh ./mvnw verify` est la barrière unique, en local comme en CI. Elle enchaîne, dans cet ordre :
+
+1. **Spotless** (`google-java-format`) : vérifie le format. `sh ./mvnw spotless:apply` le corrige.
+2. **Checkstyle** (`google_checks.xml`) : lint. Les exceptions sont dans `config/checkstyle-suppressions.xml`.
+3. **PMD** et **SpotBugs** : analyse statique.
+4. **Tests** (Surefire, classes `*Test`).
+5. **JaCoCo** : rapport dans `target/site/jacoco`, échec sous **40 %** de lignes couvertes.
+
+Le workflow `.github/workflows/ci.yml` lance cette commande dans le job `check`. Trois autres contrôles tournent sur les pull requests : `security` (Trivy, dépendances), `codeql` (code Java et workflows GitHub Actions) et Dependabot (`github-actions` et `maven`, chaque semaine). La branche `main` exige `check` et `security`.
+
+Pour des tests d'intégration `*IT`, il faut déclarer `maven-failsafe-plugin` dans le `pom.xml` : sans lui, Maven ignore ces classes sans erreur.
+
## Swagger UI
Pour visualiser et interagir avec la documentation de l'API, accédez à **Swagger UI** via l'URL suivante :
diff --git a/config/checkstyle-suppressions.xml b/config/checkstyle-suppressions.xml
new file mode 100644
index 0000000..b146a67
--- /dev/null
+++ b/config/checkstyle-suppressions.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index d9394fd..c7847af 100644
--- a/pom.xml
+++ b/pom.xml
@@ -59,6 +59,125 @@
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ 3.10.3
+
+
+
+
+
+
+
+
+ spotless
+ validate
+
+ check
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.6.0
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 14.3.0
+
+
+
+ google_checks.xml
+ config/checkstyle-suppressions.xml
+ warning
+ true
+
+
+
+ checkstyle
+ validate
+
+ check
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.28.0
+
+ true
+
+
+
+ pmd
+ process-classes
+
+ check
+
+
+
+
+
+ com.github.spotbugs
+ spotbugs-maven-plugin
+ 4.10.4.1
+
+
+ spotbugs
+ process-classes
+
+ check
+
+
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.15
+
+
+ jacoco-agent
+
+ prepare-agent
+
+
+
+ jacoco-report
+ verify
+
+ report
+
+
+
+ jacoco-check
+ verify
+
+ check
+
+
+
+
+ BUNDLE
+
+
+ LINE
+ COVEREDRATIO
+ 0.40
+
+
+
+
+
+
+
+
org.springframework.boot
spring-boot-maven-plugin
diff --git a/src/main/java/fr/kevpdev/swapi/SwaggerConfiguration.java b/src/main/java/fr/kevpdev/swapi/SwaggerConfiguration.java
index dd86c0e..4185477 100644
--- a/src/main/java/fr/kevpdev/swapi/SwaggerConfiguration.java
+++ b/src/main/java/fr/kevpdev/swapi/SwaggerConfiguration.java
@@ -8,12 +8,13 @@
@Configuration
public class SwaggerConfiguration {
- @Bean
- public OpenAPI customOpenAPI() {
- return new OpenAPI()
- .info(new Info()
- .title("API Documentation")
- .version("1.0")
- .description("Documentation for Swapi API V1.0"));
- }
+ @Bean
+ public OpenAPI customOpenApi() {
+ return new OpenAPI()
+ .info(
+ new Info()
+ .title("API Documentation")
+ .version("1.0")
+ .description("Documentation for Swapi API V1.0"));
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/SwapiApplication.java b/src/main/java/fr/kevpdev/swapi/SwapiApplication.java
index b654a8d..347d701 100644
--- a/src/main/java/fr/kevpdev/swapi/SwapiApplication.java
+++ b/src/main/java/fr/kevpdev/swapi/SwapiApplication.java
@@ -6,8 +6,7 @@
@SpringBootApplication
public class SwapiApplication {
- public static void main(String[] args) {
- SpringApplication.run(SwapiApplication.class, args);
- }
-
+ public static void main(String[] args) {
+ SpringApplication.run(SwapiApplication.class, args);
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/controllers/FilmController.java b/src/main/java/fr/kevpdev/swapi/controllers/FilmController.java
index dcde506..5731fbd 100644
--- a/src/main/java/fr/kevpdev/swapi/controllers/FilmController.java
+++ b/src/main/java/fr/kevpdev/swapi/controllers/FilmController.java
@@ -4,35 +4,36 @@
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.FilmService;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/v1/films")
public class FilmController {
- private final FilmService filmService;
+ private final FilmService filmService;
- public FilmController(FilmService filmService) {
- this.filmService = filmService;
- }
+ public FilmController(FilmService filmService) {
+ this.filmService = filmService;
+ }
- @GetMapping("/{id}")
- public Mono> getFilmById(@PathVariable int id) {
- return filmService.getFilmById(id)
- .map(ResponseEntity::ok);
- }
+ @GetMapping("/{id}")
+ public Mono> getFilmById(@PathVariable int id) {
+ return filmService.getFilmById(id).map(ResponseEntity::ok);
+ }
- @GetMapping
- public Mono>> getFilms(
- @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
- return filmService.getFilms(pageId)
- .map(ResponseEntity::ok);
- }
+ @GetMapping
+ public Mono>> getFilms(
+ @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
+ return filmService.getFilms(pageId).map(ResponseEntity::ok);
+ }
- @GetMapping("/search")
- public Mono>> getFilmByName(@RequestParam String title) {
- return filmService.getFilmByTitle(title)
- .map(ResponseEntity::ok);
- }
+ @GetMapping("/search")
+ public Mono>> getFilmByName(@RequestParam String title) {
+ return filmService.getFilmByTitle(title).map(ResponseEntity::ok);
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/controllers/PersonController.java b/src/main/java/fr/kevpdev/swapi/controllers/PersonController.java
index edbd4d6..83a128d 100644
--- a/src/main/java/fr/kevpdev/swapi/controllers/PersonController.java
+++ b/src/main/java/fr/kevpdev/swapi/controllers/PersonController.java
@@ -4,39 +4,46 @@
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.PersonService;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/v1/people")
public class PersonController {
- private final PersonService personService;
-
- public PersonController(PersonService personService) {
- this.personService = personService;
- }
-
- @GetMapping("/{id}")
- public Mono> getPersonById(@PathVariable int id) {
- return personService.getPersonById(id)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
-
- @GetMapping
- public Mono>> getPeople(
- @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
- return personService.getPeople(pageId)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
-
- @GetMapping("/search")
- public Mono>> getPersonByName(@RequestParam String name) {
- return personService.getPersonByName(name)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
-
+ private final PersonService personService;
+
+ public PersonController(PersonService personService) {
+ this.personService = personService;
+ }
+
+ @GetMapping("/{id}")
+ public Mono> getPersonById(@PathVariable int id) {
+ return personService
+ .getPersonById(id)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping
+ public Mono>> getPeople(
+ @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
+ return personService
+ .getPeople(pageId)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/search")
+ public Mono>> getPersonByName(
+ @RequestParam String name) {
+ return personService
+ .getPersonByName(name)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/controllers/PlanetController.java b/src/main/java/fr/kevpdev/swapi/controllers/PlanetController.java
index 8f67581..51fc131 100644
--- a/src/main/java/fr/kevpdev/swapi/controllers/PlanetController.java
+++ b/src/main/java/fr/kevpdev/swapi/controllers/PlanetController.java
@@ -4,38 +4,46 @@
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.PlanetService;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/api/v1/planets")
public class PlanetController {
-
- private final PlanetService planetService;
- public PlanetController(PlanetService planetService) {
- this.planetService = planetService;
- }
+ private final PlanetService planetService;
- @GetMapping("/{id}")
- public Mono> getPlanetById(@PathVariable int id) {
- return planetService.getPlanetById(id)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
+ public PlanetController(PlanetService planetService) {
+ this.planetService = planetService;
+ }
- @GetMapping
- public Mono>> getPlanets(
- @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
- return planetService.getPlanets(pageId)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
+ @GetMapping("/{id}")
+ public Mono> getPlanetById(@PathVariable int id) {
+ return planetService
+ .getPlanetById(id)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
- @GetMapping("/search")
- public Mono>> getPlanetByName(@RequestParam String name) {
- return planetService.getPlanetByName(name)
- .map(ResponseEntity::ok)
- .defaultIfEmpty(ResponseEntity.notFound().build());
- }
+ @GetMapping
+ public Mono>> getPlanets(
+ @RequestParam(value = "page", required = false, defaultValue = "1") Integer pageId) {
+ return planetService
+ .getPlanets(pageId)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
+
+ @GetMapping("/search")
+ public Mono>> getPlanetByName(
+ @RequestParam String name) {
+ return planetService
+ .getPlanetByName(name)
+ .map(ResponseEntity::ok)
+ .defaultIfEmpty(ResponseEntity.notFound().build());
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/FilmDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/FilmDTO.java
index 0164c15..ae6e28f 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/FilmDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/FilmDTO.java
@@ -1,35 +1,34 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class FilmDTO {
- private String title;
+ private String title;
- @JsonProperty("episode_id")
- private int episodeId;
+ @JsonProperty("episode_id")
+ private int episodeId;
- @JsonProperty("opening_crawl")
- private String openingCrawl;
+ @JsonProperty("opening_crawl")
+ private String openingCrawl;
- private String director;
- private String producer;
+ private String director;
+ private String producer;
- @JsonProperty("release_date")
- private String releaseDate;
+ @JsonProperty("release_date")
+ private String releaseDate;
- private List characters;
- private List planets;
- private List starships;
- private List vehicles;
- private List species;
+ private List characters;
+ private List planets;
+ private List starships;
+ private List vehicles;
+ private List species;
- private String created;
- private String edited;
- private String url;
+ private String created;
+ private String edited;
+ private String url;
}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/PersonDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/PersonDTO.java
index c551373..8a57e58 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/PersonDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/PersonDTO.java
@@ -1,38 +1,42 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class PersonDTO {
- @JsonProperty("birth_year")
- private String birthYear;
- @JsonProperty("eye_color")
- private String eyeColor;
- private List films;
- private String gender;
- @JsonProperty("hair_color")
- private String hairColor;
- private String height;
- private String homeworld;
- private String mass;
- private String name;
- @JsonProperty("skin_color")
- private String skinColor;
- private String created;
- private String edited;
- private List species;
- private List starships;
- private String url;
- private List vehicles;
-
- /* lists with data */
- private List filmsDTO;
- private List starshipsDTO;
- private List vehiclesDTO;
+ @JsonProperty("birth_year")
+ private String birthYear;
+
+ @JsonProperty("eye_color")
+ private String eyeColor;
+
+ private List films;
+ private String gender;
+
+ @JsonProperty("hair_color")
+ private String hairColor;
+
+ private String height;
+ private String homeworld;
+ private String mass;
+ private String name;
+
+ @JsonProperty("skin_color")
+ private String skinColor;
+
+ private String created;
+ private String edited;
+ private List species;
+ private List starships;
+ private String url;
+ private List vehicles;
+ /* lists with data */
+ private List filmsDTO;
+ private List starshipsDTO;
+ private List vehiclesDTO;
}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/PlanetDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/PlanetDTO.java
index 48749ec..1236102 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/PlanetDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/PlanetDTO.java
@@ -1,35 +1,34 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class PlanetDTO {
- private String name;
+ private String name;
- @JsonProperty("rotation_period")
- private String rotationPeriod;
+ @JsonProperty("rotation_period")
+ private String rotationPeriod;
- @JsonProperty("orbital_period")
- private String orbitalPeriod;
+ @JsonProperty("orbital_period")
+ private String orbitalPeriod;
- private String diameter;
- private String climate;
- private String gravity;
- private String terrain;
+ private String diameter;
+ private String climate;
+ private String gravity;
+ private String terrain;
- @JsonProperty("surface_water")
- private String surfaceWater;
+ @JsonProperty("surface_water")
+ private String surfaceWater;
- private String population;
- private List residents;
- private List films;
+ private String population;
+ private List residents;
+ private List films;
- private String created;
- private String edited;
- private String url;
+ private String created;
+ private String edited;
+ private String url;
}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/SearchResultDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/SearchResultDTO.java
index 3a89b25..2eb2a5f 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/SearchResultDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/SearchResultDTO.java
@@ -1,17 +1,15 @@
package fr.kevpdev.swapi.dtos;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
-public class SearchResultDTO {
-
- public Integer count;
- public String next;
- public String previous;
- public List results;
+public class SearchResultDTO {
+ private Integer count;
+ private String next;
+ private String previous;
+ private List results;
}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/SpeciesDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/SpeciesDTO.java
index e6144f5..8c992bc 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/SpeciesDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/SpeciesDTO.java
@@ -1,39 +1,38 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class SpeciesDTO {
- private String name;
- private String classification;
- private String designation;
+ private String name;
+ private String classification;
+ private String designation;
- @JsonProperty("average_height")
- private String averageHeight;
+ @JsonProperty("average_height")
+ private String averageHeight;
- @JsonProperty("skin_colors")
- private String skinColors;
+ @JsonProperty("skin_colors")
+ private String skinColors;
- @JsonProperty("hair_colors")
- private String hairColors;
+ @JsonProperty("hair_colors")
+ private String hairColors;
- @JsonProperty("eye_colors")
- private String eyeColors;
+ @JsonProperty("eye_colors")
+ private String eyeColors;
- @JsonProperty("average_lifespan")
- private String averageLifespan;
+ @JsonProperty("average_lifespan")
+ private String averageLifespan;
- private String homeworld;
- private String language;
- private List people;
- private List films;
+ private String homeworld;
+ private String language;
+ private List people;
+ private List films;
- private String created;
- private String edited;
- private String url;
-}
\ No newline at end of file
+ private String created;
+ private String edited;
+ private String url;
+}
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/StarshipDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/StarshipDTO.java
index ff3fd54..a984837 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/StarshipDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/StarshipDTO.java
@@ -1,47 +1,45 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class StarshipDTO {
- private String name;
- private String model;
- private String manufacturer;
+ private String name;
+ private String model;
+ private String manufacturer;
- @JsonProperty("cost_in_credits")
- private String costInCredits;
+ @JsonProperty("cost_in_credits")
+ private String costInCredits;
- private String length;
+ private String length;
- @JsonProperty("max_atmosphering_speed")
- private String maxAtmospheringSpeed;
+ @JsonProperty("max_atmosphering_speed")
+ private String maxAtmospheringSpeed;
- private String crew;
- private String passengers;
+ private String crew;
+ private String passengers;
- @JsonProperty("cargo_capacity")
- private String cargoCapacity;
+ @JsonProperty("cargo_capacity")
+ private String cargoCapacity;
- private String consumables;
+ private String consumables;
- @JsonProperty("hyperdrive_rating")
- private String hyperdriveRating;
+ @JsonProperty("hyperdrive_rating")
+ private String hyperdriveRating;
- private String MGLT;
+ private String MGLT;
- @JsonProperty("starship_class")
- private String starshipClass;
+ @JsonProperty("starship_class")
+ private String starshipClass;
- private List pilots;
- private List films;
+ private List pilots;
+ private List films;
- private String created;
- private String edited;
- private String url;
+ private String created;
+ private String edited;
+ private String url;
}
-
diff --git a/src/main/java/fr/kevpdev/swapi/dtos/VehicleDTO.java b/src/main/java/fr/kevpdev/swapi/dtos/VehicleDTO.java
index ebbdc81..34f0811 100644
--- a/src/main/java/fr/kevpdev/swapi/dtos/VehicleDTO.java
+++ b/src/main/java/fr/kevpdev/swapi/dtos/VehicleDTO.java
@@ -1,42 +1,40 @@
package fr.kevpdev.swapi.dtos;
import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
import lombok.Builder;
import lombok.Data;
-import java.util.List;
-
@Data
@Builder
public class VehicleDTO {
- private String name;
- private String model;
- private String manufacturer;
+ private String name;
+ private String model;
+ private String manufacturer;
- @JsonProperty("cost_in_credits")
- private String costInCredits;
+ @JsonProperty("cost_in_credits")
+ private String costInCredits;
- private String length;
+ private String length;
- @JsonProperty("max_atmosphering_speed")
- private String maxAtmospheringSpeed;
+ @JsonProperty("max_atmosphering_speed")
+ private String maxAtmospheringSpeed;
- private String crew;
- private String passengers;
+ private String crew;
+ private String passengers;
- @JsonProperty("cargo_capacity")
- private String cargoCapacity;
+ @JsonProperty("cargo_capacity")
+ private String cargoCapacity;
- private String consumables;
+ private String consumables;
- @JsonProperty("vehicle_class")
- private String vehicleClass;
+ @JsonProperty("vehicle_class")
+ private String vehicleClass;
- private List pilots;
- private List films;
+ private List pilots;
+ private List films;
- private String created;
- private String edited;
- private String url;
+ private String created;
+ private String edited;
+ private String url;
}
-
diff --git a/src/main/java/fr/kevpdev/swapi/exceptions/ErrorDetail.java b/src/main/java/fr/kevpdev/swapi/exceptions/ErrorDetail.java
index 24be53c..36bd66f 100644
--- a/src/main/java/fr/kevpdev/swapi/exceptions/ErrorDetail.java
+++ b/src/main/java/fr/kevpdev/swapi/exceptions/ErrorDetail.java
@@ -1,19 +1,18 @@
package fr.kevpdev.swapi.exceptions;
-import lombok.Data;
-
import java.util.Date;
+import lombok.Data;
@Data
public class ErrorDetail {
- private Date timestamp;
- private int statusCode;
- private String message;
+ private Date timestamp;
+ private int statusCode;
+ private String message;
- public ErrorDetail(int statusCode, String message) {
- this.timestamp = new Date();
- this.statusCode = statusCode;
- this.message = message;
- }
+ public ErrorDetail(int statusCode, String message) {
+ this.timestamp = new Date();
+ this.statusCode = statusCode;
+ this.message = message;
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/exceptions/GlobalExceptionHandler.java b/src/main/java/fr/kevpdev/swapi/exceptions/GlobalExceptionHandler.java
index 00d86f0..de2a030 100644
--- a/src/main/java/fr/kevpdev/swapi/exceptions/GlobalExceptionHandler.java
+++ b/src/main/java/fr/kevpdev/swapi/exceptions/GlobalExceptionHandler.java
@@ -9,22 +9,22 @@
@ControllerAdvice
public class GlobalExceptionHandler {
- @ExceptionHandler(WebClientResponseException.class)
- public ResponseEntity handleWebClientResponseException(WebClientResponseException ex) {
- HttpStatus status = (HttpStatus) ex.getStatusCode();
- String message = ex.getMessage();
+ @ExceptionHandler(WebClientResponseException.class)
+ public ResponseEntity handleWebClientResponseException(
+ WebClientResponseException ex) {
+ HttpStatus status = (HttpStatus) ex.getStatusCode();
+ String message = ex.getMessage();
- ErrorDetail errorDetail = new ErrorDetail(status.value(), message);
+ ErrorDetail errorDetail = new ErrorDetail(status.value(), message);
- return ResponseEntity.status(status).body(errorDetail);
- }
+ return ResponseEntity.status(status).body(errorDetail);
+ }
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity handleGenericException(Exception ex) {
+ String message = "Erreur inattendue : " + ex.getMessage();
+ ErrorDetail errorDetail = new ErrorDetail(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
- @ExceptionHandler(Exception.class)
- public ResponseEntity handleGenericException(Exception ex) {
- String message = "Erreur inattendue : " + ex.getMessage();
- ErrorDetail errorDetail = new ErrorDetail(HttpStatus.INTERNAL_SERVER_ERROR.value(), message);
-
- return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorDetail);
- }
+ return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorDetail);
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/FilmService.java b/src/main/java/fr/kevpdev/swapi/services/FilmService.java
index 5c97c42..75a511f 100644
--- a/src/main/java/fr/kevpdev/swapi/services/FilmService.java
+++ b/src/main/java/fr/kevpdev/swapi/services/FilmService.java
@@ -6,7 +6,9 @@
public interface FilmService {
- Mono getFilmById(Integer id);
- Mono> getFilms(Integer pageId);
- Mono> getFilmByTitle(String title);
+ Mono getFilmById(Integer id);
+
+ Mono> getFilms(Integer pageId);
+
+ Mono> getFilmByTitle(String title);
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/PersonService.java b/src/main/java/fr/kevpdev/swapi/services/PersonService.java
index 4f690b5..d9f9226 100644
--- a/src/main/java/fr/kevpdev/swapi/services/PersonService.java
+++ b/src/main/java/fr/kevpdev/swapi/services/PersonService.java
@@ -4,11 +4,11 @@
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import reactor.core.publisher.Mono;
-
public interface PersonService {
- Mono getPersonById(Integer id);
- Mono> getPeople(Integer pageId);
- Mono> getPersonByName(String name);
+ Mono getPersonById(Integer id);
+
+ Mono> getPeople(Integer pageId);
+ Mono> getPersonByName(String name);
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/PlanetService.java b/src/main/java/fr/kevpdev/swapi/services/PlanetService.java
index 51fd4bf..568e196 100644
--- a/src/main/java/fr/kevpdev/swapi/services/PlanetService.java
+++ b/src/main/java/fr/kevpdev/swapi/services/PlanetService.java
@@ -6,7 +6,9 @@
public interface PlanetService {
- Mono getPlanetById(Integer id);
- Mono> getPlanets(Integer pageId);
- Mono> getPlanetByName(String name);
+ Mono getPlanetById(Integer id);
+
+ Mono> getPlanets(Integer pageId);
+
+ Mono> getPlanetByName(String name);
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/impl/FilmServiceImpl.java b/src/main/java/fr/kevpdev/swapi/services/impl/FilmServiceImpl.java
index 5030405..8e2dcdf 100644
--- a/src/main/java/fr/kevpdev/swapi/services/impl/FilmServiceImpl.java
+++ b/src/main/java/fr/kevpdev/swapi/services/impl/FilmServiceImpl.java
@@ -11,49 +11,50 @@
@Service
public class FilmServiceImpl implements FilmService {
- private final WebClient webClient;
+ private final WebClient webClient;
- public FilmServiceImpl(WebClient.Builder webClient) {
- this.webClient = webClient.baseUrl("https://swapi.dev/api/films").build();
- }
+ public FilmServiceImpl(WebClient.Builder webClient) {
+ this.webClient = webClient.baseUrl("https://swapi.dev/api/films").build();
+ }
- /**
- * Retrives a film by ID
- * @param id film ID
- * @return a Mono containing the FilmDTO object if found or empty if not
- */
- @Override
- public Mono getFilmById(Integer id) {
- return webClient.get()
- .uri("/{id}", id)
- .retrieve()
- .bodyToMono(FilmDTO.class);
- }
+ /**
+ * Retrives a film by ID
+ *
+ * @param id film ID
+ * @return a Mono containing the FilmDTO object if found or empty if not
+ */
+ @Override
+ public Mono getFilmById(Integer id) {
+ return webClient.get().uri("/{id}", id).retrieve().bodyToMono(FilmDTO.class);
+ }
- /**
- * Retrives all film with pagination
- *
- * @param pageId Pagination number
- * @return a Mono containing the filmDTO object containing a FilmDTO array
- */
- @Override
- public Mono> getFilms(Integer pageId) {
- return webClient.get()
- .uri("/?page={pageId}", pageId)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all film with pagination
+ *
+ * @param pageId Pagination number
+ * @return a Mono containing the filmDTO object containing a FilmDTO array
+ */
+ @Override
+ public Mono> getFilms(Integer pageId) {
+ return webClient
+ .get()
+ .uri("/?page={pageId}", pageId)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
- /**
- * Retrives all films by title
- * @param title film title
- * @return a Mono containing the FilmDTO object list if found or empty if not
- */
- @Override
- public Mono> getFilmByTitle(String title) {
- return webClient.get()
- .uri("/?search={title}", title)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all films by title
+ *
+ * @param title film title
+ * @return a Mono containing the FilmDTO object list if found or empty if not
+ */
+ @Override
+ public Mono> getFilmByTitle(String title) {
+ return webClient
+ .get()
+ .uri("/?search={title}", title)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/impl/PersonServiceImpl.java b/src/main/java/fr/kevpdev/swapi/services/impl/PersonServiceImpl.java
index 33c5590..40ec33b 100644
--- a/src/main/java/fr/kevpdev/swapi/services/impl/PersonServiceImpl.java
+++ b/src/main/java/fr/kevpdev/swapi/services/impl/PersonServiceImpl.java
@@ -1,7 +1,13 @@
package fr.kevpdev.swapi.services.impl;
-import fr.kevpdev.swapi.dtos.*;
+import fr.kevpdev.swapi.dtos.FilmDTO;
+import fr.kevpdev.swapi.dtos.PersonDTO;
+import fr.kevpdev.swapi.dtos.SearchResultDTO;
+import fr.kevpdev.swapi.dtos.StarshipDTO;
+import fr.kevpdev.swapi.dtos.VehicleDTO;
import fr.kevpdev.swapi.services.PersonService;
+import java.net.URI;
+import java.util.List;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
@@ -9,93 +15,98 @@
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
-import java.net.URI;
-import java.util.List;
-
@Service
public class PersonServiceImpl implements PersonService {
- private final WebClient webClient;
-
- @Value("${swapi.url}")
- private String swapiUri;
+ private final WebClient webClient;
- public PersonServiceImpl(WebClient.Builder client) {
- this.webClient = client.baseUrl("https://swapi.dev/api/people").build();
- }
+ @Value("${swapi.url}")
+ private String swapiUri;
+ public PersonServiceImpl(WebClient.Builder client) {
+ this.webClient = client.baseUrl("https://swapi.dev/api/people").build();
+ }
- /**
- * Retrives a person by ID
- * @param id person ID
- * @return a Mono containing the PersonDTO object if found or empty if not
- */
- @Override
- public Mono getPersonById(Integer id) {
- return webClient.get()
- .uri("/{id}", id)
- .retrieve()
- .bodyToMono(PersonDTO.class)
- .flatMap(personDTO -> {
+ /**
+ * Retrives a person by ID
+ *
+ * @param id person ID
+ * @return a Mono containing the PersonDTO object if found or empty if not
+ */
+ @Override
+ public Mono getPersonById(Integer id) {
+ return webClient
+ .get()
+ .uri("/{id}", id)
+ .retrieve()
+ .bodyToMono(PersonDTO.class)
+ .flatMap(
+ personDTO -> {
- // Exemple pour la curiosité de récupération des DTO
- // Mais je ne vais pas étendre car aucune indication des besoins du front et aussi moyen pour les perfs
- // L'utilisation d'un cache serait cool pour eviter les appels inutiles
- Mono> monoFilmsDTO = getResourcesByUrls(personDTO.getFilms(), FilmDTO.class);
- Mono> monoStarshipsDTO = getResourcesByUrls(personDTO.getStarships(), StarshipDTO.class);
- Mono> monoVehiclesDTO = getResourcesByUrls(personDTO.getStarships(), VehicleDTO.class);
+ // Exemple pour la curiosité de récupération des DTO
+ // Mais je ne vais pas étendre car aucune indication des besoins du front et aussi
+ // moyen pour les perfs
+ // L'utilisation d'un cache serait cool pour eviter les appels inutiles
+ Mono> monoFilmsDTO =
+ getResourcesByUrls(personDTO.getFilms(), FilmDTO.class);
+ Mono> monoStarshipsDTO =
+ getResourcesByUrls(personDTO.getStarships(), StarshipDTO.class);
+ Mono> monoVehiclesDTO =
+ getResourcesByUrls(personDTO.getStarships(), VehicleDTO.class);
- return Mono.zip(monoFilmsDTO, monoStarshipsDTO,monoVehiclesDTO).map(data -> {
+ return Mono.zip(monoFilmsDTO, monoStarshipsDTO, monoVehiclesDTO)
+ .map(
+ data -> {
personDTO.setFilmsDTO(data.getT1());
personDTO.setStarshipsDTO(data.getT2());
personDTO.setVehiclesDTO(data.getT3());
return personDTO;
- });
- });
- }
-
- /**
- * Retrives all people with pagination
- *
- * @param pageId Pagination number
- * @return a Mono containing the SearchResultDTO object containing a PersonDTO array
- */
- @Override
- public Mono> getPeople(Integer pageId) {
+ });
+ });
+ }
- return webClient.get()
- .uri("/?page={pageId}", pageId)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all people with pagination
+ *
+ * @param pageId Pagination number
+ * @return a Mono containing the SearchResultDTO object containing a PersonDTO array
+ */
+ @Override
+ public Mono> getPeople(Integer pageId) {
+ return webClient
+ .get()
+ .uri("/?page={pageId}", pageId)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
- /**
- * Retrives all people by name
- * @param name person name
- * @return a Mono containing the PersonDTO object list if found or empty if not
- */
- @Override
- public Mono> getPersonByName(String name) {
- return webClient.get()
- .uri("/?search={name}", name)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all people by name
+ *
+ * @param name person name
+ * @return a Mono containing the PersonDTO object list if found or empty if not
+ */
+ @Override
+ public Mono> getPersonByName(String name) {
+ return webClient
+ .get()
+ .uri("/?search={name}", name)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
- /**
- * Retrieves DTO object list by hypermedia link
- * @param urls hypermedialink list
- * @param responseType DTO type
- * @return a Mono containing the Generic DTO object list if found or empty if not
- * @param
- */
- public Mono> getResourcesByUrls(List urls, Class responseType) {
- return Flux.fromIterable(urls)
- .flatMap(url -> webClient.get()
- .uri(URI.create(url))
- .retrieve()
- .bodyToMono(responseType))
- .collectList();
- }
+ /**
+ * Retrieves DTO object list by hypermedia link
+ *
+ * @param DTO type
+ * @param urls hypermedialink list
+ * @param responseType DTO type
+ * @return a Mono containing the Generic DTO object list if found or empty if not
+ */
+ public Mono> getResourcesByUrls(List urls, Class responseType) {
+ return Flux.fromIterable(urls)
+ .flatMap(url -> webClient.get().uri(URI.create(url)).retrieve().bodyToMono(responseType))
+ .collectList();
+ }
}
diff --git a/src/main/java/fr/kevpdev/swapi/services/impl/PlanetServiceImpl.java b/src/main/java/fr/kevpdev/swapi/services/impl/PlanetServiceImpl.java
index 0fbb07b..6a09d0b 100644
--- a/src/main/java/fr/kevpdev/swapi/services/impl/PlanetServiceImpl.java
+++ b/src/main/java/fr/kevpdev/swapi/services/impl/PlanetServiceImpl.java
@@ -11,49 +11,50 @@
@Service
public class PlanetServiceImpl implements PlanetService {
- private final WebClient webClient;
+ private final WebClient webClient;
- public PlanetServiceImpl(WebClient.Builder webClient) {
- this.webClient = webClient.baseUrl("https://swapi.dev/api/planets").build();
- }
+ public PlanetServiceImpl(WebClient.Builder webClient) {
+ this.webClient = webClient.baseUrl("https://swapi.dev/api/planets").build();
+ }
- /**
- * Retrives a planet by ID
- * @param id planet ID
- * @return a Mono containing the PlanetDTO object if found or empty if not
- */
- @Override
- public Mono getPlanetById(Integer id) {
- return webClient.get()
- .uri("/{id}", id)
- .retrieve()
- .bodyToMono(PlanetDTO.class);
- }
+ /**
+ * Retrives a planet by ID
+ *
+ * @param id planet ID
+ * @return a Mono containing the PlanetDTO object if found or empty if not
+ */
+ @Override
+ public Mono getPlanetById(Integer id) {
+ return webClient.get().uri("/{id}", id).retrieve().bodyToMono(PlanetDTO.class);
+ }
- /**
- * Retrives all planets with pagination
- *
- * @param pageId Pagination number
- * @return a Mono containing the SearchResultDTO object containing a PlanetDTO array
- */
- @Override
- public Mono> getPlanets(Integer pageId) {
- return webClient.get()
- .uri("/?page={pageId}", pageId)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all planets with pagination
+ *
+ * @param pageId Pagination number
+ * @return a Mono containing the SearchResultDTO object containing a PlanetDTO array
+ */
+ @Override
+ public Mono> getPlanets(Integer pageId) {
+ return webClient
+ .get()
+ .uri("/?page={pageId}", pageId)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
- /**
- * Retrives all planets by name
- * @param name planet name
- * @return a Mono containing the PlanetDTO object list if found or empty if not
- */
- @Override
- public Mono> getPlanetByName(String name) {
- return webClient.get()
- .uri("/?search={name}", name)
- .retrieve()
- .bodyToMono(new ParameterizedTypeReference>() {});
- }
+ /**
+ * Retrives all planets by name
+ *
+ * @param name planet name
+ * @return a Mono containing the PlanetDTO object list if found or empty if not
+ */
+ @Override
+ public Mono> getPlanetByName(String name) {
+ return webClient
+ .get()
+ .uri("/?search={name}", name)
+ .retrieve()
+ .bodyToMono(new ParameterizedTypeReference>() {});
+ }
}
diff --git a/src/test/java/fr/kevpdev/swapi/SwapiApplicationTests.java b/src/test/java/fr/kevpdev/swapi/SwapiApplicationTests.java
index b91dcb5..be8aa23 100644
--- a/src/test/java/fr/kevpdev/swapi/SwapiApplicationTests.java
+++ b/src/test/java/fr/kevpdev/swapi/SwapiApplicationTests.java
@@ -6,8 +6,6 @@
@SpringBootTest
class SwapiApplicationTests {
- @Test
- void contextLoads() {
- }
-
+ @Test
+ void contextLoads() {}
}
diff --git a/src/test/java/fr/kevpdev/swapi/controllers/FilmControllerTest.java b/src/test/java/fr/kevpdev/swapi/controllers/FilmControllerTest.java
index 0085390..89fcd3f 100644
--- a/src/test/java/fr/kevpdev/swapi/controllers/FilmControllerTest.java
+++ b/src/test/java/fr/kevpdev/swapi/controllers/FilmControllerTest.java
@@ -1,8 +1,12 @@
package fr.kevpdev.swapi.controllers;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import fr.kevpdev.swapi.dtos.FilmDTO;
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.FilmService;
+import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,103 +16,90 @@
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
-import java.util.List;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@WebFluxTest(FilmController.class)
class FilmControllerTest {
- private static final String PATH = "/api/v1/films";
- private FilmDTO filmDTO;
-
- private SearchResultDTO searchResultDTO;
-
- @Autowired
- private WebTestClient webTestClient;
-
- @MockBean
- private FilmService filmService;
-
- @BeforeEach
- public void setup() {
- this.filmDTO = FilmDTO.builder()
- .title("A New Hope")
- .episodeId(4)
- .openingCrawl("It is a period of civil war...")
- .director("George Lucas")
- .producer("Gary Kurtz, Rick McCallum")
- .releaseDate("1977-05-25")
- .characters(List.of(
- "https://swapi.dev/api/people/1/",
- "https://swapi.dev/api/people/2/",
- "https://swapi.dev/api/people/3/",
- "https://swapi.dev/api/people/4/"
- ))
- .planets(List.of(
- "https://swapi.dev/api/planets/1/",
- "https://swapi.dev/api/planets/2/",
- "https://swapi.dev/api/planets/3/"
- ))
- .starships(List.of(
- "https://swapi.dev/api/starships/2/",
- "https://swapi.dev/api/starships/3/",
- "https://swapi.dev/api/starships/5/"
- ))
- .vehicles(List.of(
- "https://swapi.dev/api/vehicles/4/",
- "https://swapi.dev/api/vehicles/6/"
- ))
- .species(List.of(
- "https://swapi.dev/api/species/1/",
- "https://swapi.dev/api/species/2/"
- ))
- .created("2014-12-10T14:23:31.880000Z")
- .edited("2014-12-20T19:49:45.256000Z")
- .url("https://swapi.dev/api/films/1/")
- .build();
-
-
- this.searchResultDTO = SearchResultDTO.builder()
- .count(6)
- .previous(null)
- .results(List.of(filmDTO))
- .build();
- }
-
- @Test
- public void shouldReturnFilmByIdWhenFilmIdValid() {
-
- when(filmService.getFilmById(1)).thenReturn(Mono.just(filmDTO));
-
- webTestClient.get().uri(PATH+"/1")
- .exchange()
- .expectStatus().isOk()
- .expectBody(FilmDTO.class)
- .isEqualTo(filmDTO);
-
- verify(filmService).getFilmById(1);
- }
-
- @Test
- public void shouldReturn404ErrorFilmByIdWhenFilmNotFound() {
-
- when(filmService.getFilmById(1)).thenReturn(
- Mono.error(
- WebClientResponseException
- .create(404, "Film not Found", null, null, null)));
-
- webTestClient.get().uri(PATH+"/1")
- .exchange()
- .expectStatus().isNotFound();
-
- verify(filmService).getFilmById(1);
-
- }
-
- /*
- TODO...
- */
-
-}
\ No newline at end of file
+ private static final String PATH = "/api/v1/films";
+ private FilmDTO filmDTO;
+
+ private SearchResultDTO searchResultDTO;
+
+ @Autowired private WebTestClient webTestClient;
+
+ @MockBean private FilmService filmService;
+
+ @BeforeEach
+ public void setup() {
+ this.filmDTO =
+ FilmDTO.builder()
+ .title("A New Hope")
+ .episodeId(4)
+ .openingCrawl("It is a period of civil war...")
+ .director("George Lucas")
+ .producer("Gary Kurtz, Rick McCallum")
+ .releaseDate("1977-05-25")
+ .characters(
+ List.of(
+ "https://swapi.dev/api/people/1/",
+ "https://swapi.dev/api/people/2/",
+ "https://swapi.dev/api/people/3/",
+ "https://swapi.dev/api/people/4/"))
+ .planets(
+ List.of(
+ "https://swapi.dev/api/planets/1/",
+ "https://swapi.dev/api/planets/2/",
+ "https://swapi.dev/api/planets/3/"))
+ .starships(
+ List.of(
+ "https://swapi.dev/api/starships/2/",
+ "https://swapi.dev/api/starships/3/",
+ "https://swapi.dev/api/starships/5/"))
+ .vehicles(
+ List.of("https://swapi.dev/api/vehicles/4/", "https://swapi.dev/api/vehicles/6/"))
+ .species(
+ List.of("https://swapi.dev/api/species/1/", "https://swapi.dev/api/species/2/"))
+ .created("2014-12-10T14:23:31.880000Z")
+ .edited("2014-12-20T19:49:45.256000Z")
+ .url("https://swapi.dev/api/films/1/")
+ .build();
+
+ this.searchResultDTO =
+ SearchResultDTO.builder()
+ .count(6)
+ .previous(null)
+ .results(List.of(filmDTO))
+ .build();
+ }
+
+ @Test
+ public void shouldReturnFilmByIdWhenFilmIdValid() {
+
+ when(filmService.getFilmById(1)).thenReturn(Mono.just(filmDTO));
+
+ webTestClient
+ .get()
+ .uri(PATH + "/1")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(FilmDTO.class)
+ .isEqualTo(filmDTO);
+
+ verify(filmService).getFilmById(1);
+ }
+
+ @Test
+ public void shouldReturn404ErrorFilmByIdWhenFilmNotFound() {
+
+ when(filmService.getFilmById(1))
+ .thenReturn(
+ Mono.error(WebClientResponseException.create(404, "Film not Found", null, null, null)));
+
+ webTestClient.get().uri(PATH + "/1").exchange().expectStatus().isNotFound();
+
+ verify(filmService).getFilmById(1);
+ }
+
+ // TODO: complete these tests
+
+}
diff --git a/src/test/java/fr/kevpdev/swapi/controllers/PersonControllerTest.java b/src/test/java/fr/kevpdev/swapi/controllers/PersonControllerTest.java
index 552e1ab..fc3ad21 100644
--- a/src/test/java/fr/kevpdev/swapi/controllers/PersonControllerTest.java
+++ b/src/test/java/fr/kevpdev/swapi/controllers/PersonControllerTest.java
@@ -1,8 +1,13 @@
package fr.kevpdev.swapi.controllers;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import fr.kevpdev.swapi.dtos.PersonDTO;
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.PersonService;
+import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -13,179 +18,164 @@
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
-import java.util.List;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@WebFluxTest(PersonController.class)
class PersonControllerTest {
- private static final String PATH = "/api/v1/people";
- private PersonDTO personDTO;
-
- private SearchResultDTO searchResultDTO;
-
- @Autowired
- private WebTestClient webTestClient;
-
- @MockBean
- private PersonService personService;
-
- @BeforeEach
- public void setup() {
- this.personDTO = PersonDTO.builder()
- .name("Luke Skywalker")
- .birthYear("19BBY")
- .eyeColor("Blue")
- .gender("Male")
- .hairColor("Blond")
- .height("172")
- .mass("77")
- .homeworld("https://swapi.dev/api/planets/1/")
- .films(List.of("https://swapi.dev/api/films/1/", "https://swapi.dev/api/films/2/"))
- .species(List.of())
- .starships(List.of("https://swapi.dev/api/starships/12/"))
- .vehicles(List.of("https://swapi.dev/api/vehicles/14/"))
- .created("2014-12-09T13:50:51.644000Z")
- .edited("2014-12-20T21:17:56.891000Z")
- .url("https://swapi.dev/api/people/1/")
- .build();
-
- this.searchResultDTO = SearchResultDTO.builder()
- .count(82)
- .previous(null)
- .results(List.of(personDTO))
- .build();
- }
-
-
- @Test
- public void ShouldReturnPersonByIdWhenStatusIsOK() {
-
- when(personService.getPersonById(1)).thenReturn(Mono.just(personDTO));
-
- webTestClient.get().uri(PATH+"/1")
- .exchange()
- .expectStatus().isOk()
- .expectBody(PersonDTO.class)
- .isEqualTo(personDTO);
-
- verify(personService).getPersonById(1);
-
- }
-
- @Test
- public void ShouldTReturn404ErrorWhenEmptyPerson() {
-
- when(personService.getPersonById(100))
- .thenReturn(Mono
- .error(WebClientResponseException
- .create(404,"", null, null, null)));
-
- webTestClient.get().uri(PATH+"/100")
- .exchange()
- .expectStatus().isNotFound();
-
- verify(personService).getPersonById(100);
-
- }
-
- @Test
- public void ShouldReturnAllPersonWhenPageIdNotEmpty() {
-
- shouldReturnAllPeopleWhenStatusOK(1);
-
- }
-
- @Test
- public void ShouldReturnAllPersonWhenEmptyPageId() {
-
- shouldReturnAllPeopleWhenStatusOK(null);
-
- }
-
- /**
- * Test to retrieve all people when status is OK with a pageId param.
- * If pageId is null, then default page number is 1
- * @param pageId Page number for the pagination
- */
- private void shouldReturnAllPeopleWhenStatusOK(Integer pageId) {
-
- when(personService.getPeople(1)).thenReturn(Mono.just(searchResultDTO));
-
- webTestClient.get()
- .uri(uriBuilder -> {
- var builder = uriBuilder.path(PATH);
- if (pageId != null) {
- builder.queryParam("page", pageId);
- }
- return builder.build();
- })
- .exchange()
- .expectStatus().isOk()
- .expectBody(new ParameterizedTypeReference>() {})
- .isEqualTo(searchResultDTO);
-
- verify(personService).getPeople(1);
- }
-
-
- @Test
- public void ShouldReturn404ErrorWhenSearchResultisNotFound() {
-
- when(personService.getPeople(1)).thenReturn(Mono
- .error(WebClientResponseException
- .create(404,"", null, null, null)));
-
- webTestClient.get().uri(uriBuilder -> uriBuilder
- .path(PATH)
- .queryParam("page", 1)
- .build())
- .exchange()
- .expectStatus().isNotFound();
-
- verify(personService).getPeople(1);
-
- }
-
- @Test
- public void ShouldReturnPersonByNameWhenStatusIsOk() {
-
- when(personService.getPersonByName(anyString())).thenReturn(Mono.just(searchResultDTO));
- String name = "Luke SkyWalker";
- webTestClient.get()
- .uri(uriBuilder -> uriBuilder.path(PATH+"/search")
- .queryParam("name", name)
- .build())
- .exchange()
- .expectStatus().isOk()
- .expectBody(new ParameterizedTypeReference>() {})
- .isEqualTo(searchResultDTO);
-
- verify(personService).getPersonByName(name);
-
- }
-
- @Test
- public void ShouldReturn404ErrorWhenPersonByNameIsNotFound() {
-
- String name = "Luke SkyWalker";
-
- when(personService.getPersonByName(name))
- .thenReturn(Mono
- .error(WebClientResponseException
- .create(404,"", null, null, null)));
-
- webTestClient.get()
- .uri(uriBuilder -> uriBuilder.path(PATH+"/search")
- .queryParam("name", name)
- .build())
- .exchange()
- .expectStatus().isNotFound();
-
- verify(personService).getPersonByName(name);
-
- }
-}
\ No newline at end of file
+ private static final String PATH = "/api/v1/people";
+ private PersonDTO personDTO;
+
+ private SearchResultDTO searchResultDTO;
+
+ @Autowired private WebTestClient webTestClient;
+
+ @MockBean private PersonService personService;
+
+ @BeforeEach
+ public void setup() {
+ this.personDTO =
+ PersonDTO.builder()
+ .name("Luke Skywalker")
+ .birthYear("19BBY")
+ .eyeColor("Blue")
+ .gender("Male")
+ .hairColor("Blond")
+ .height("172")
+ .mass("77")
+ .homeworld("https://swapi.dev/api/planets/1/")
+ .films(List.of("https://swapi.dev/api/films/1/", "https://swapi.dev/api/films/2/"))
+ .species(List.of())
+ .starships(List.of("https://swapi.dev/api/starships/12/"))
+ .vehicles(List.of("https://swapi.dev/api/vehicles/14/"))
+ .created("2014-12-09T13:50:51.644000Z")
+ .edited("2014-12-20T21:17:56.891000Z")
+ .url("https://swapi.dev/api/people/1/")
+ .build();
+
+ this.searchResultDTO =
+ SearchResultDTO.builder()
+ .count(82)
+ .previous(null)
+ .results(List.of(personDTO))
+ .build();
+ }
+
+ @Test
+ public void ShouldReturnPersonByIdWhenStatusIsOK() {
+
+ when(personService.getPersonById(1)).thenReturn(Mono.just(personDTO));
+
+ webTestClient
+ .get()
+ .uri(PATH + "/1")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(PersonDTO.class)
+ .isEqualTo(personDTO);
+
+ verify(personService).getPersonById(1);
+ }
+
+ @Test
+ public void ShouldTReturn404ErrorWhenEmptyPerson() {
+
+ when(personService.getPersonById(100))
+ .thenReturn(Mono.error(WebClientResponseException.create(404, "", null, null, null)));
+
+ webTestClient.get().uri(PATH + "/100").exchange().expectStatus().isNotFound();
+
+ verify(personService).getPersonById(100);
+ }
+
+ @Test
+ public void ShouldReturnAllPersonWhenPageIdNotEmpty() {
+
+ shouldReturnAllPeopleWhenStatusOK(1);
+ }
+
+ @Test
+ public void ShouldReturnAllPersonWhenEmptyPageId() {
+
+ shouldReturnAllPeopleWhenStatusOK(null);
+ }
+
+ /**
+ * Test to retrieve all people when status is OK with a pageId param. If pageId is null, then
+ * default page number is 1
+ *
+ * @param pageId Page number for the pagination
+ */
+ private void shouldReturnAllPeopleWhenStatusOK(Integer pageId) {
+
+ when(personService.getPeople(1)).thenReturn(Mono.just(searchResultDTO));
+
+ webTestClient
+ .get()
+ .uri(
+ uriBuilder -> {
+ var builder = uriBuilder.path(PATH);
+ if (pageId != null) {
+ builder.queryParam("page", pageId);
+ }
+ return builder.build();
+ })
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(new ParameterizedTypeReference>() {})
+ .isEqualTo(searchResultDTO);
+
+ verify(personService).getPeople(1);
+ }
+
+ @Test
+ public void ShouldReturn404ErrorWhenSearchResultisNotFound() {
+
+ when(personService.getPeople(1))
+ .thenReturn(Mono.error(WebClientResponseException.create(404, "", null, null, null)));
+
+ webTestClient
+ .get()
+ .uri(uriBuilder -> uriBuilder.path(PATH).queryParam("page", 1).build())
+ .exchange()
+ .expectStatus()
+ .isNotFound();
+
+ verify(personService).getPeople(1);
+ }
+
+ @Test
+ public void ShouldReturnPersonByNameWhenStatusIsOk() {
+
+ when(personService.getPersonByName(anyString())).thenReturn(Mono.just(searchResultDTO));
+ String name = "Luke SkyWalker";
+ webTestClient
+ .get()
+ .uri(uriBuilder -> uriBuilder.path(PATH + "/search").queryParam("name", name).build())
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(new ParameterizedTypeReference>() {})
+ .isEqualTo(searchResultDTO);
+
+ verify(personService).getPersonByName(name);
+ }
+
+ @Test
+ public void ShouldReturn404ErrorWhenPersonByNameIsNotFound() {
+
+ String name = "Luke SkyWalker";
+
+ when(personService.getPersonByName(name))
+ .thenReturn(Mono.error(WebClientResponseException.create(404, "", null, null, null)));
+
+ webTestClient
+ .get()
+ .uri(uriBuilder -> uriBuilder.path(PATH + "/search").queryParam("name", name).build())
+ .exchange()
+ .expectStatus()
+ .isNotFound();
+
+ verify(personService).getPersonByName(name);
+ }
+}
diff --git a/src/test/java/fr/kevpdev/swapi/controllers/PlanetControllerTest.java b/src/test/java/fr/kevpdev/swapi/controllers/PlanetControllerTest.java
index 50ff546..545298b 100644
--- a/src/test/java/fr/kevpdev/swapi/controllers/PlanetControllerTest.java
+++ b/src/test/java/fr/kevpdev/swapi/controllers/PlanetControllerTest.java
@@ -1,8 +1,12 @@
package fr.kevpdev.swapi.controllers;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import fr.kevpdev.swapi.dtos.PlanetDTO;
import fr.kevpdev.swapi.dtos.SearchResultDTO;
import fr.kevpdev.swapi.services.PlanetService;
+import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -12,78 +16,68 @@
import org.springframework.web.reactive.function.client.WebClientResponseException;
import reactor.core.publisher.Mono;
-import java.util.List;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@WebFluxTest(PlanetController.class)
class PlanetControllerTest {
- private static final String PATH = "/api/v1/planets";
- private PlanetDTO planetDTO;
-
- private SearchResultDTO searchResultDTO;
-
- @Autowired
- private WebTestClient webTestClient;
+ private static final String PATH = "/api/v1/planets";
+ private PlanetDTO planetDTO;
- @MockBean
- private PlanetService planetService;
+ private SearchResultDTO searchResultDTO;
- @BeforeEach
- void setUp() {
+ @Autowired private WebTestClient webTestClient;
- this.planetDTO = PlanetDTO.builder()
- .name("Yavin IV")
- .rotationPeriod("24")
- .orbitalPeriod("4818")
- .diameter("10200")
- .climate("temperate, tropical")
- .gravity("1 standard")
- .terrain("jungle, rainforests")
- .surfaceWater("8")
- .population("1000")
- .residents(List.of()) // Liste vide
- .films(List.of("https://swapi.dev/api/films/1/"))
- .created("2014-12-10T11:37:19.144000Z")
- .edited("2014-12-20T20:58:18.421000Z")
- .url("https://swapi.dev/api/planets/3/")
- .build();
+ @MockBean private PlanetService planetService;
- }
+ @BeforeEach
+ void setUp() {
- @Test
- public void shouldReturnFilmByIdWhenFilmIdValid() {
+ this.planetDTO =
+ PlanetDTO.builder()
+ .name("Yavin IV")
+ .rotationPeriod("24")
+ .orbitalPeriod("4818")
+ .diameter("10200")
+ .climate("temperate, tropical")
+ .gravity("1 standard")
+ .terrain("jungle, rainforests")
+ .surfaceWater("8")
+ .population("1000")
+ .residents(List.of()) // Liste vide
+ .films(List.of("https://swapi.dev/api/films/1/"))
+ .created("2014-12-10T11:37:19.144000Z")
+ .edited("2014-12-20T20:58:18.421000Z")
+ .url("https://swapi.dev/api/planets/3/")
+ .build();
+ }
- when(planetService.getPlanetById(1)).thenReturn(Mono.just(planetDTO));
+ @Test
+ public void shouldReturnFilmByIdWhenFilmIdValid() {
- webTestClient.get().uri(PATH+"/1")
- .exchange()
- .expectStatus().isOk()
- .expectBody(PlanetDTO.class)
- .isEqualTo(planetDTO);
+ when(planetService.getPlanetById(1)).thenReturn(Mono.just(planetDTO));
- verify(planetService).getPlanetById(1);
- }
+ webTestClient
+ .get()
+ .uri(PATH + "/1")
+ .exchange()
+ .expectStatus()
+ .isOk()
+ .expectBody(PlanetDTO.class)
+ .isEqualTo(planetDTO);
- @Test
- public void shouldReturn404ErrorFilmByIdWhenFilmNotFound() {
+ verify(planetService).getPlanetById(1);
+ }
- when(planetService.getPlanetById(1)).thenReturn(
- Mono.error(
- WebClientResponseException
- .create(404, "Film not Found", null, null, null)));
+ @Test
+ public void shouldReturn404ErrorFilmByIdWhenFilmNotFound() {
- webTestClient.get().uri(PATH+"/1")
- .exchange()
- .expectStatus().isNotFound();
+ when(planetService.getPlanetById(1))
+ .thenReturn(
+ Mono.error(WebClientResponseException.create(404, "Film not Found", null, null, null)));
- verify(planetService).getPlanetById(1);
+ webTestClient.get().uri(PATH + "/1").exchange().expectStatus().isNotFound();
- }
+ verify(planetService).getPlanetById(1);
+ }
- /*
- TODO...
- */
-}
\ No newline at end of file
+ // TODO: complete these tests
+}