From bcb63f320989ae139423bcb8bf51cbe26cc54779 Mon Sep 17 00:00:00 2001 From: Pavlo Bystrytskyi Date: Wed, 16 Oct 2024 15:08:52 +0200 Subject: [PATCH 1/4] ISSUE-12: Create a POST create new relation actor-movie-relation endpoint and cover it with tests. --- .../backend/controller/ActorController.java | 5 - .../controller/ActorMovieController.java | 28 +++ .../backend/controller/MovieController.java | 5 +- .../example/backend/dto/ErrorResponse.java | 4 + .../com/example/backend/dto/IdRequest.java | 6 + .../exception/GlobalExceptionHandler.java | 47 +++++ .../java/com/example/backend/model/Actor.java | 4 +- .../backend/model/ActorMovieRelation.java | 27 +++ .../model/ActorMovieRelationRepository.java | 11 + .../backend/model/ActorRepository.java | 5 - .../com/example/backend/model/Director.java | 4 +- .../java/com/example/backend/model/Movie.java | 7 +- .../backend/service/ActorMovieService.java | 30 +++ .../example/backend/service/ActorService.java | 6 +- .../example/backend/service/MovieService.java | 5 +- .../controller/ActorControllerTest.java | 66 +----- .../controller/ActorMovieControllerTest.java | 195 ++++++++++++++++++ .../controller/MovieControllerTest.java | 17 +- 18 files changed, 369 insertions(+), 103 deletions(-) create mode 100644 backend/src/main/java/com/example/backend/controller/ActorMovieController.java create mode 100644 backend/src/main/java/com/example/backend/dto/ErrorResponse.java create mode 100644 backend/src/main/java/com/example/backend/dto/IdRequest.java create mode 100644 backend/src/main/java/com/example/backend/exception/GlobalExceptionHandler.java create mode 100644 backend/src/main/java/com/example/backend/model/ActorMovieRelation.java create mode 100644 backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java create mode 100644 backend/src/main/java/com/example/backend/service/ActorMovieService.java create mode 100644 backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java diff --git a/backend/src/main/java/com/example/backend/controller/ActorController.java b/backend/src/main/java/com/example/backend/controller/ActorController.java index 7faeca4..e73732d 100644 --- a/backend/src/main/java/com/example/backend/controller/ActorController.java +++ b/backend/src/main/java/com/example/backend/controller/ActorController.java @@ -32,11 +32,6 @@ public List getByName(@PathVariable @NonNull String prefix) { return actorService.getActorsByPrefix(prefix).stream().map(ActorResponse::from).toList(); } - @GetMapping("/movie/{movieId}") - public List getByMovieId(@PathVariable @NonNull Long movieId) { - return actorService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList(); - } - @PutMapping public void update() { // TODO diff --git a/backend/src/main/java/com/example/backend/controller/ActorMovieController.java b/backend/src/main/java/com/example/backend/controller/ActorMovieController.java new file mode 100644 index 0000000..f0aa66e --- /dev/null +++ b/backend/src/main/java/com/example/backend/controller/ActorMovieController.java @@ -0,0 +1,28 @@ +package com.example.backend.controller; + +import com.example.backend.dto.ActorResponse; +import com.example.backend.dto.IdRequest; +import com.example.backend.service.ActorMovieService; +import lombok.AllArgsConstructor; +import lombok.NonNull; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/actor-movie") +public class ActorMovieController { + + private final ActorMovieService actorMovieService; + + @PostMapping("/{movieId}") + public void addActorById(@PathVariable @NonNull Long movieId, @RequestBody IdRequest idRequest) { + actorMovieService.addActor(movieId, idRequest.id()); + } + + @GetMapping("/{movieId}") + public List getActorsByMovieId(@PathVariable @NonNull Long movieId) { + return actorMovieService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList(); + } +} diff --git a/backend/src/main/java/com/example/backend/controller/MovieController.java b/backend/src/main/java/com/example/backend/controller/MovieController.java index 0d2ded2..ace5125 100644 --- a/backend/src/main/java/com/example/backend/controller/MovieController.java +++ b/backend/src/main/java/com/example/backend/controller/MovieController.java @@ -18,12 +18,13 @@ public class MovieController { private final MovieService movieService; @PostMapping - public MovieResponse save(@RequestBody @NotNull CreateMovieRequest movieRequest){ + public MovieResponse save(@RequestBody @NotNull CreateMovieRequest movieRequest) { Movie movie = movieRequest.toMovie(); return MovieResponse.from(movieService.createMovie(movie)); } + @GetMapping - public List getAll(){ + public List getAll() { return movieService.getAllMovies().stream().map(MovieResponse::from).collect(Collectors.toList()); } } diff --git a/backend/src/main/java/com/example/backend/dto/ErrorResponse.java b/backend/src/main/java/com/example/backend/dto/ErrorResponse.java new file mode 100644 index 0000000..f0bcf01 --- /dev/null +++ b/backend/src/main/java/com/example/backend/dto/ErrorResponse.java @@ -0,0 +1,4 @@ +package com.example.backend.dto; + +public record ErrorResponse(String message) { +} diff --git a/backend/src/main/java/com/example/backend/dto/IdRequest.java b/backend/src/main/java/com/example/backend/dto/IdRequest.java new file mode 100644 index 0000000..004d0c3 --- /dev/null +++ b/backend/src/main/java/com/example/backend/dto/IdRequest.java @@ -0,0 +1,6 @@ +package com.example.backend.dto; + +import lombok.NonNull; + +public record IdRequest(@NonNull Long id) { +} diff --git a/backend/src/main/java/com/example/backend/exception/GlobalExceptionHandler.java b/backend/src/main/java/com/example/backend/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..bd54161 --- /dev/null +++ b/backend/src/main/java/com/example/backend/exception/GlobalExceptionHandler.java @@ -0,0 +1,47 @@ +package com.example.backend.exception; + +import com.example.backend.dto.ErrorResponse; +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpStatus; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.resource.NoResourceFoundException; + +import java.util.NoSuchElementException; +import java.util.logging.Logger; + +@ControllerAdvice +@Log4j2 +public class GlobalExceptionHandler { + private static final String GENERIC_ERROR_MESSAGE = "Something went wrong"; + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleGlobalException(NoSuchElementException exception) { + log.info(exception.getMessage()); + return new ErrorResponse(exception.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + public ErrorResponse handleGlobalException(HttpMessageNotReadableException exception) { + log.info(exception.getMessage()); + return new ErrorResponse(exception.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + public ErrorResponse handleGlobalException(NoResourceFoundException exception) { + log.info(exception.getMessage()); + return new ErrorResponse(exception.getMessage()); + } + + @ExceptionHandler + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) + public ErrorResponse handleGlobalException(Exception exception) { + log.error(exception); + return new ErrorResponse(GENERIC_ERROR_MESSAGE); + } +} diff --git a/backend/src/main/java/com/example/backend/model/Actor.java b/backend/src/main/java/com/example/backend/model/Actor.java index 4fcf8c6..bd34c8a 100644 --- a/backend/src/main/java/com/example/backend/model/Actor.java +++ b/backend/src/main/java/com/example/backend/model/Actor.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.*; +import java.util.HashSet; import java.util.Set; @Entity @@ -17,9 +18,6 @@ public class Actor { @GeneratedValue private Long id; - @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) - private Set movies; - @Column(nullable = false) private String name; } diff --git a/backend/src/main/java/com/example/backend/model/ActorMovieRelation.java b/backend/src/main/java/com/example/backend/model/ActorMovieRelation.java new file mode 100644 index 0000000..0168647 --- /dev/null +++ b/backend/src/main/java/com/example/backend/model/ActorMovieRelation.java @@ -0,0 +1,27 @@ +package com.example.backend.model; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Builder +@With +@Data +@Table( + uniqueConstraints = { + @UniqueConstraint(columnNames = {"actor_id", "movie_id"}) + } +) +public class ActorMovieRelation { + @Id + @GeneratedValue + private Long id; + + @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}) + private Actor actor; + + @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}) + private Movie movie; +} diff --git a/backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java b/backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java new file mode 100644 index 0000000..c12c0ef --- /dev/null +++ b/backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java @@ -0,0 +1,11 @@ +package com.example.backend.model; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ActorMovieRelationRepository extends JpaRepository { + List findByMovieId(Long movieId); +} diff --git a/backend/src/main/java/com/example/backend/model/ActorRepository.java b/backend/src/main/java/com/example/backend/model/ActorRepository.java index accd214..1ddfa7b 100644 --- a/backend/src/main/java/com/example/backend/model/ActorRepository.java +++ b/backend/src/main/java/com/example/backend/model/ActorRepository.java @@ -1,8 +1,6 @@ package com.example.backend.model; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; @@ -10,7 +8,4 @@ @Repository public interface ActorRepository extends JpaRepository { List findByNameStartingWith(String prefix); - - @Query("SELECT a FROM Actor a JOIN a.movies m WHERE m.id = :movieId") - List findByMovieId(@Param("movieId") Long movieId); } diff --git a/backend/src/main/java/com/example/backend/model/Director.java b/backend/src/main/java/com/example/backend/model/Director.java index f06615b..fb33183 100644 --- a/backend/src/main/java/com/example/backend/model/Director.java +++ b/backend/src/main/java/com/example/backend/model/Director.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.*; +import java.util.HashSet; import java.util.Set; @Entity @@ -17,8 +18,5 @@ public class Director { @GeneratedValue private Long id; - @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) - private Set movies; - private String name; } diff --git a/backend/src/main/java/com/example/backend/model/Movie.java b/backend/src/main/java/com/example/backend/model/Movie.java index ade1a45..d2bda30 100644 --- a/backend/src/main/java/com/example/backend/model/Movie.java +++ b/backend/src/main/java/com/example/backend/model/Movie.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.*; +import java.util.HashSet; import java.util.Set; @Entity @@ -22,11 +23,5 @@ public class Movie { private boolean isWatched; - @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) - private Set actors; - - @ManyToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER) - private Set directors; - private String name; } diff --git a/backend/src/main/java/com/example/backend/service/ActorMovieService.java b/backend/src/main/java/com/example/backend/service/ActorMovieService.java new file mode 100644 index 0000000..c3f7106 --- /dev/null +++ b/backend/src/main/java/com/example/backend/service/ActorMovieService.java @@ -0,0 +1,30 @@ +package com.example.backend.service; + +import com.example.backend.model.*; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ActorMovieService { + private final ActorMovieRelationRepository actorMovieRelationRepository; + + private final ActorRepository actorRepository; + + private final MovieRepository movieRepository; + + public List getActorsByMovieId(Long movieId) { + return actorMovieRelationRepository.findByMovieId(movieId) + .stream() + .map(ActorMovieRelation::getActor) + .toList(); + } + + public void addActor(Long movieId, Long actorId) { + Movie movie = movieRepository.findById(movieId).orElseThrow(); + Actor actor = actorRepository.findById(actorId).orElseThrow(); + actorMovieRelationRepository.save(ActorMovieRelation.builder().actor(actor).movie(movie).actor(actor).build()); + } +} diff --git a/backend/src/main/java/com/example/backend/service/ActorService.java b/backend/src/main/java/com/example/backend/service/ActorService.java index da460b6..30cde2b 100644 --- a/backend/src/main/java/com/example/backend/service/ActorService.java +++ b/backend/src/main/java/com/example/backend/service/ActorService.java @@ -1,6 +1,8 @@ package com.example.backend.service; import com.example.backend.model.Actor; +import com.example.backend.model.ActorMovieRelation; +import com.example.backend.model.ActorMovieRelationRepository; import com.example.backend.model.ActorRepository; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; @@ -23,8 +25,4 @@ public List getAllActors() { public List getActorsByPrefix(String prefix) { return actorRepository.findByNameStartingWith(prefix); } - - public List getActorsByMovieId(Long movieId) { - return actorRepository.findByMovieId(movieId); - } } diff --git a/backend/src/main/java/com/example/backend/service/MovieService.java b/backend/src/main/java/com/example/backend/service/MovieService.java index b35a76c..35e5301 100644 --- a/backend/src/main/java/com/example/backend/service/MovieService.java +++ b/backend/src/main/java/com/example/backend/service/MovieService.java @@ -1,9 +1,9 @@ package com.example.backend.service; -import com.example.backend.model.Movie; -import com.example.backend.model.MovieRepository; +import com.example.backend.model.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; + import java.util.List; @Service @@ -14,6 +14,7 @@ public class MovieService { public Movie createMovie(Movie movie) { return movieRepository.save(movie); } + public List getAllMovies() { return movieRepository.findAll(); } diff --git a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java index a6e49a1..3ef8822 100644 --- a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java @@ -1,9 +1,6 @@ package com.example.backend.controller; -import com.example.backend.model.Actor; -import com.example.backend.model.ActorRepository; -import com.example.backend.model.Movie; -import com.example.backend.model.MovieRepository; +import com.example.backend.model.*; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -15,8 +12,8 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import java.util.List; -import java.util.Set; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasSize; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -26,7 +23,6 @@ class ActorControllerTest { private static final String URL_BASE = "/api/actor"; private static final String URL_AUTOCOMPLETION = "/api/actor/autocompletion/{prefix}"; - private static final String URL_GET_BY_MOVIE = "/api/actor/movie/{movieId}"; private static final long ID_FIRST = 1L; private static final long ID_SECOND = 2L; @@ -45,6 +41,9 @@ class ActorControllerTest { @Autowired private MovieRepository movieRepository; + @Autowired + private ActorMovieRelationRepository actorMovieRelationRepository; + @Test @DirtiesContext void saveTest_correct() throws Exception { @@ -60,7 +59,7 @@ void saveTest_correct() throws Exception { .andExpect(MockMvcResultMatchers.status().isOk()); List actual = actorRepository.findAll(); - List expected = List.of(Actor.builder().id(ID_FIRST).movies(Set.of()).name(NAME_JOHN).build()); + List expected = List.of(Actor.builder().id(ID_FIRST).name(NAME_JOHN).build()); assertEquals(expected, actual); } @@ -80,7 +79,7 @@ void saveTest_correct_idIgnored() throws Exception { .andExpect(MockMvcResultMatchers.status().isOk()); List actual = actorRepository.findAll(); - List expected = List.of(Actor.builder().id(ID_FIRST).movies(Set.of()).name(NAME_JANE).build()); + List expected = List.of(Actor.builder().id(ID_FIRST).name(NAME_JANE).build()); assertEquals(expected, actual); } @@ -162,55 +161,4 @@ void getByNameTest_emptyRequest() throws Exception { .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } - @Test - @DirtiesContext - void getByMovieIdTest_multipleMatch() throws Exception { - Movie movieFirst = Movie.builder().name("Some Movie Name First").build(); - Movie movieSecond = Movie.builder().name("Some Movie Name Second").build(); - - movieRepository.saveAll(List.of(movieFirst, movieSecond)); - - actorRepository.saveAll( - List.of( - Actor.builder().name(NAME_JANE).movies(Set.of(movieFirst)).build(), - Actor.builder().name(NAME_JIM).movies(Set.of(movieFirst, movieSecond)).build(), - Actor.builder().name(NAME_JOE).movies(Set.of(movieSecond)).build(), - Actor.builder().name(NAME_JOHN).movies(Set.of()).build() - ) - ); - - mvc.perform(MockMvcRequestBuilders.get(URL_GET_BY_MOVIE, movieSecond.getId())) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andExpect(jsonPath("$", hasSize(2))) - .andExpect(jsonPath("$[0].name").value(NAME_JIM)) - .andExpect(jsonPath("$[1].name").value(NAME_JOE)); - } - - @Test - @DirtiesContext - void getByMovieIdTest_noMatch() throws Exception { - Movie movieFirst = Movie.builder().name("Some Movie Name First").build(); - Movie movieSecond = Movie.builder().name("Some Movie Name Second").build(); - - movieRepository.saveAll(List.of(movieFirst, movieSecond)); - - actorRepository.saveAll( - List.of( - Actor.builder().name(NAME_JANE).movies(Set.of(movieFirst)).build(), - Actor.builder().name(NAME_JIM).movies(Set.of(movieFirst)).build(), - Actor.builder().name(NAME_JOE).movies(Set.of(movieFirst)).build(), - Actor.builder().name(NAME_JOHN).movies(Set.of()).build() - ) - ); - - mvc.perform(MockMvcRequestBuilders.get(URL_GET_BY_MOVIE, movieSecond.getId())) - .andExpect(MockMvcResultMatchers.status().isOk()) - .andExpect(jsonPath("$", hasSize(0))); - } - - @Test - void getByMovieIdTest_emptyRequest() throws Exception { - mvc.perform(MockMvcRequestBuilders.get(URL_GET_BY_MOVIE, "")) - .andExpect(MockMvcResultMatchers.status().is4xxClientError()); - } } \ No newline at end of file diff --git a/backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java b/backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java new file mode 100644 index 0000000..8388eed --- /dev/null +++ b/backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java @@ -0,0 +1,195 @@ +package com.example.backend.controller; + +import com.example.backend.model.*; +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.annotation.DirtiesContext; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.hasSize; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +@SpringBootTest +@AutoConfigureMockMvc +class ActorMovieControllerTest { + private static final String URL_ACTOR_MOVIE_BASE = "/api/actor-movie/{movieId}"; + + private static final String ACTOR_NAME_JANE = "Jane Doe"; + private static final String ACTOR_NAME_JIM = "Jim Doe"; + private static final String ACTOR_NAME_JOE = "Joe Doe"; + private static final String ACTOR_NAME_JOHN = "John Doe"; + + private static final String MOVIE_NAME_MEMENTO = "Memento"; + private static final String MOVIE_NAME_DEADPOOL = "Deadpool"; + + @Autowired + private MockMvc mockMvc; + + @Autowired + private MovieRepository movieRepository; + + @Autowired + private ActorRepository actorRepository; + + @Autowired + private ActorMovieRelationRepository actorMovieRelationRepository; + + @Test + @DirtiesContext + void getByMovieIdTest_multipleMatch() throws Exception { + Movie movieFirst = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Movie movieSecond = Movie.builder().name(MOVIE_NAME_DEADPOOL).build(); + Actor actorJane = Actor.builder().name(ACTOR_NAME_JANE).build(); + Actor actorJim = Actor.builder().name(ACTOR_NAME_JIM).build(); + Actor actorJoe = Actor.builder().name(ACTOR_NAME_JOE).build(); + Actor actorJohn = Actor.builder().name(ACTOR_NAME_JOHN).build(); + movieRepository.saveAll(List.of(movieFirst, movieSecond)); + actorRepository.saveAll(List.of(actorJane, actorJim, actorJoe, actorJohn)); + actorMovieRelationRepository.saveAll( + List.of( + ActorMovieRelation.builder().actor(actorJane).movie(movieFirst).build(), + ActorMovieRelation.builder().actor(actorJoe).movie(movieSecond).build(), + ActorMovieRelation.builder().actor(actorJim).movie(movieSecond).build(), + ActorMovieRelation.builder().actor(actorJane).movie(movieSecond).build() + ) + ); + + mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, movieSecond.getId())) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", hasSize(3))) + .andExpect(jsonPath("$[*].name", containsInAnyOrder( + actorJoe.getName(), + actorJim.getName(), + actorJane.getName() + ))); + } + + @Test + @DirtiesContext + void getByMovieIdTest_noMatch() throws Exception { + Movie movieFirst = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Movie movieSecond = Movie.builder().name(MOVIE_NAME_DEADPOOL).build(); + Actor actorJane = Actor.builder().name(ACTOR_NAME_JANE).build(); + Actor actorJim = Actor.builder().name(ACTOR_NAME_JIM).build(); + Actor actorJoe = Actor.builder().name(ACTOR_NAME_JOE).build(); + Actor actorJohn = Actor.builder().name(ACTOR_NAME_JOHN).build(); + movieRepository.saveAll(List.of(movieFirst, movieSecond)); + actorRepository.saveAll(List.of(actorJane, actorJim, actorJoe, actorJohn)); + actorMovieRelationRepository.saveAll( + List.of( + ActorMovieRelation.builder().actor(actorJane).movie(movieFirst).build(), + ActorMovieRelation.builder().actor(actorJoe).movie(movieFirst).build(), + ActorMovieRelation.builder().actor(actorJim).movie(movieFirst).build(), + ActorMovieRelation.builder().actor(actorJohn).movie(movieFirst).build() + ) + ); + + mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, movieSecond.getId())) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(jsonPath("$", hasSize(0))); + } + + @Test + void getByMovieIdTest_emptyRequest() throws Exception { + mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, "")) + .andExpect(MockMvcResultMatchers.status().is4xxClientError()); + } + + @Test + @DirtiesContext + void addActorById_successFull() throws Exception { + Movie movie = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Actor actor = Actor.builder().name(ACTOR_NAME_JANE).build(); + movieRepository.save(movie); + actorRepository.save(actor); + + mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content( + """ + { + "id": "%s" + } + """.formatted(actor.getId()) + ) + ) + .andExpect(MockMvcResultMatchers.status().isOk()); + + List actualActorIdList = actorMovieRelationRepository.findByMovieId(movie.getId()); + assertEquals(1, actualActorIdList.size()); + assertEquals(actor.getId(), actualActorIdList.getFirst().getActor().getId()); + } + + @Test + @DirtiesContext + void addActorById_alreadyAdded() throws Exception { + Movie movie = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Actor actor = Actor.builder().name(ACTOR_NAME_JANE).build(); + movieRepository.save(movie); + actorRepository.save(actor); + actorMovieRelationRepository.save(ActorMovieRelation.builder().actor(actor).movie(movie).build()); + + mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content( + """ + { + "id": "%s" + } + """.formatted(actor.getId()) + )) + .andExpect(MockMvcResultMatchers.status().is5xxServerError()); + } + + @Test + @DirtiesContext + void addActorById_noSuchActor() throws Exception { + Movie movie = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Actor actor = Actor.builder().name(ACTOR_NAME_JANE).build(); + movieRepository.save(movie); + actorRepository.save(actor); + Long nonExistentActorId = actor.getId() + 1; + + mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content( + """ + { + "id": "%s" + } + """.formatted(nonExistentActorId) + )) + .andExpect(MockMvcResultMatchers.status().is4xxClientError()); + } + + @Test + @DirtiesContext + void addActorById_noSuchMovie() throws Exception { + Movie movie = Movie.builder().name(MOVIE_NAME_MEMENTO).build(); + Actor actor = Actor.builder().name(ACTOR_NAME_JANE).build(); + movieRepository.save(movie); + actorRepository.save(actor); + Long nonExistentMovieId = movie.getId() + 1L; + + mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, nonExistentMovieId) + .contentType(MediaType.APPLICATION_JSON) + .content( + """ + { + "id": "%s" + } + """.formatted(actor.getId()) + )) + + .andExpect(MockMvcResultMatchers.status().is4xxClientError()); + } +} \ No newline at end of file diff --git a/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java b/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java index d2973b6..f5fdac7 100644 --- a/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java @@ -1,11 +1,6 @@ package com.example.backend.controller; -import com.example.backend.dto.MovieResponse; -import org.junit.jupiter.api.Test; -import com.example.backend.model.Actor; -import com.example.backend.model.ActorRepository; -import com.example.backend.model.Movie; -import com.example.backend.model.MovieRepository; +import com.example.backend.model.*; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -17,22 +12,17 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import java.util.List; -import java.util.Set; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.junit.jupiter.api.Assertions.*; @SpringBootTest @AutoConfigureMockMvc class MovieControllerTest { private static final String URL_BASE = "/api/movie"; - private static final long ID_FIRST = 1L; - private static final long ID_SECOND = 2L; private static final String NAME_MEMENTO = "Memento"; private static final String NAME_DEADPOOL = "Deadpool"; @@ -43,7 +33,6 @@ class MovieControllerTest { @Autowired private MovieRepository movieRepository; - @Test @DirtiesContext void saveTest_correct() throws Exception { @@ -59,7 +48,7 @@ void saveTest_correct() throws Exception { )) .andExpect(MockMvcResultMatchers.status().isOk()); List actualMovies = movieRepository.findAll(); - List expectedMovies = List.of(Movie.builder().id(ID_FIRST).name(NAME_MEMENTO).isWatched(true).actors(Set.of()).directors(Set.of()).build()); + List expectedMovies = List.of(Movie.builder().id(ID_FIRST).name(NAME_MEMENTO).isWatched(true).build()); assertEquals(expectedMovies, actualMovies); } @Test From 878a750529e3d09be077d3183049be7672dd1a89 Mon Sep 17 00:00:00 2001 From: Pavlo Bystrytskyi Date: Wed, 16 Oct 2024 18:03:58 +0200 Subject: [PATCH 2/4] ISSUE-12: Create a POST create new relation actor-movie-relation endpoint and cover it with tests. --- .../example/backend/service/MovieService.java | 19 ++++++------------- .../controller/ActorControllerTest.java | 1 - .../controller/MovieControllerTest.java | 3 --- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/backend/src/main/java/com/example/backend/service/MovieService.java b/backend/src/main/java/com/example/backend/service/MovieService.java index a870747..75b1afe 100644 --- a/backend/src/main/java/com/example/backend/service/MovieService.java +++ b/backend/src/main/java/com/example/backend/service/MovieService.java @@ -3,9 +3,7 @@ import com.example.backend.model.Movie; import com.example.backend.model.MovieRepository; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import org.springframework.web.server.ResponseStatusException; import java.util.List; @@ -23,22 +21,17 @@ public List getAllMovies() { } public Movie getMovieById(Long movieId) { - return movieRepository.findById(movieId) - .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movieId + " not found")); + return movieRepository.findById(movieId).orElseThrow(); } public void deleteMovie(Long movieId) { - if (movieRepository.existsById(movieId)) { - movieRepository.deleteById(movieId); - } else { - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movieId + " does not exist"); - } + movieRepository.findById(movieId).orElseThrow(); + movieRepository.deleteById(movieId); } public Movie updateMovie(Movie movie) { - if (movieRepository.existsById(movie.getId())) { - return movieRepository.save(movie); - } - throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie with id " + movie.getId() + " does not exist"); + movieRepository.findById(movie.getId()).orElseThrow(); + + return movieRepository.save(movie); } } diff --git a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java index 3ef8822..8c6de48 100644 --- a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java @@ -13,7 +13,6 @@ import java.util.List; -import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.hasSize; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; diff --git a/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java b/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java index e4e64d5..f3cb38e 100644 --- a/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/MovieControllerTest.java @@ -12,14 +12,11 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import java.util.List; -import java.util.Set; import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.junit.jupiter.api.Assertions.*; - @SpringBootTest @AutoConfigureMockMvc class MovieControllerTest { From cbb2bbd54190726983210fb13cf890095283db48 Mon Sep 17 00:00:00 2001 From: Pavlo Bystrytskyi Date: Thu, 17 Oct 2024 09:30:52 +0200 Subject: [PATCH 3/4] ISSUE-12: Create a POST create new relation actor-movie-relation endpoint and cover it with tests. --- .../main/java/com/example/backend/service/MovieService.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/com/example/backend/service/MovieService.java b/backend/src/main/java/com/example/backend/service/MovieService.java index 75b1afe..7438aa0 100644 --- a/backend/src/main/java/com/example/backend/service/MovieService.java +++ b/backend/src/main/java/com/example/backend/service/MovieService.java @@ -25,8 +25,9 @@ public Movie getMovieById(Long movieId) { } public void deleteMovie(Long movieId) { - movieRepository.findById(movieId).orElseThrow(); - movieRepository.deleteById(movieId); + Movie movie = movieRepository.findById(movieId).orElseThrow(); + + movieRepository.delete(movie); } public Movie updateMovie(Movie movie) { From 0f9084100bacef839da6872d183a5b3db3225873 Mon Sep 17 00:00:00 2001 From: Pavlo Bystrytskyi Date: Thu, 17 Oct 2024 11:57:04 +0200 Subject: [PATCH 4/4] ISSUE-12: Create a POST create new relation actor-movie-relation endpoint and cover it with tests. --- ...troller.java => MovieActorController.java} | 18 +++--- .../com/example/backend/dto/IdRequest.java | 6 -- .../backend/dto/MovieActorRequest.java | 6 ++ ...eRelation.java => MovieActorRelation.java} | 2 +- ...java => MovieActorRelationRepository.java} | 4 +- .../example/backend/service/ActorService.java | 2 - ...vieService.java => MovieActorService.java} | 10 +-- .../controller/ActorControllerTest.java | 2 +- ...est.java => MovieActorControllerTest.java} | 61 ++++++++++--------- 9 files changed, 57 insertions(+), 54 deletions(-) rename backend/src/main/java/com/example/backend/controller/{ActorMovieController.java => MovieActorController.java} (64%) delete mode 100644 backend/src/main/java/com/example/backend/dto/IdRequest.java create mode 100644 backend/src/main/java/com/example/backend/dto/MovieActorRequest.java rename backend/src/main/java/com/example/backend/model/{ActorMovieRelation.java => MovieActorRelation.java} (94%) rename backend/src/main/java/com/example/backend/model/{ActorMovieRelationRepository.java => MovieActorRelationRepository.java} (54%) rename backend/src/main/java/com/example/backend/service/{ActorMovieService.java => MovieActorService.java} (72%) rename backend/src/test/java/com/example/backend/controller/{ActorMovieControllerTest.java => MovieActorControllerTest.java} (78%) diff --git a/backend/src/main/java/com/example/backend/controller/ActorMovieController.java b/backend/src/main/java/com/example/backend/controller/MovieActorController.java similarity index 64% rename from backend/src/main/java/com/example/backend/controller/ActorMovieController.java rename to backend/src/main/java/com/example/backend/controller/MovieActorController.java index dc81658..18953d0 100644 --- a/backend/src/main/java/com/example/backend/controller/ActorMovieController.java +++ b/backend/src/main/java/com/example/backend/controller/MovieActorController.java @@ -1,8 +1,8 @@ package com.example.backend.controller; import com.example.backend.dto.ActorResponse; -import com.example.backend.dto.IdRequest; -import com.example.backend.service.ActorMovieService; +import com.example.backend.dto.MovieActorRequest; +import com.example.backend.service.MovieActorService; import lombok.AllArgsConstructor; import lombok.NonNull; import org.springframework.http.HttpMethod; @@ -13,19 +13,19 @@ @RestController @AllArgsConstructor -@RequestMapping("/api/actor-movie") -public class ActorMovieController { +@RequestMapping("/api/movie-actor") +public class MovieActorController { - private final ActorMovieService actorMovieService; + private final MovieActorService movieActorService; - @PostMapping("/{movieId}") - public void addActorById(@PathVariable @NonNull Long movieId, @RequestBody IdRequest idRequest) { - actorMovieService.addActor(movieId, idRequest.id()); + @PostMapping() + public void addActorById(@RequestBody @NonNull MovieActorRequest movieActorRequest) { + movieActorService.addActor(movieActorRequest.movieId(), movieActorRequest.actorId()); } @GetMapping("/{movieId}") public List getActorsByMovieId(@PathVariable @NonNull Long movieId) { - return actorMovieService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList(); + return movieActorService.getActorsByMovieId(movieId).stream().map(ActorResponse::from).toList(); } /** diff --git a/backend/src/main/java/com/example/backend/dto/IdRequest.java b/backend/src/main/java/com/example/backend/dto/IdRequest.java deleted file mode 100644 index 004d0c3..0000000 --- a/backend/src/main/java/com/example/backend/dto/IdRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.example.backend.dto; - -import lombok.NonNull; - -public record IdRequest(@NonNull Long id) { -} diff --git a/backend/src/main/java/com/example/backend/dto/MovieActorRequest.java b/backend/src/main/java/com/example/backend/dto/MovieActorRequest.java new file mode 100644 index 0000000..53e1ceb --- /dev/null +++ b/backend/src/main/java/com/example/backend/dto/MovieActorRequest.java @@ -0,0 +1,6 @@ +package com.example.backend.dto; + +import lombok.NonNull; + +public record MovieActorRequest(@NonNull Long movieId, @NonNull Long actorId) { +} diff --git a/backend/src/main/java/com/example/backend/model/ActorMovieRelation.java b/backend/src/main/java/com/example/backend/model/MovieActorRelation.java similarity index 94% rename from backend/src/main/java/com/example/backend/model/ActorMovieRelation.java rename to backend/src/main/java/com/example/backend/model/MovieActorRelation.java index 0168647..64cb8ba 100644 --- a/backend/src/main/java/com/example/backend/model/ActorMovieRelation.java +++ b/backend/src/main/java/com/example/backend/model/MovieActorRelation.java @@ -14,7 +14,7 @@ @UniqueConstraint(columnNames = {"actor_id", "movie_id"}) } ) -public class ActorMovieRelation { +public class MovieActorRelation { @Id @GeneratedValue private Long id; diff --git a/backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java b/backend/src/main/java/com/example/backend/model/MovieActorRelationRepository.java similarity index 54% rename from backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java rename to backend/src/main/java/com/example/backend/model/MovieActorRelationRepository.java index c12c0ef..89cf51e 100644 --- a/backend/src/main/java/com/example/backend/model/ActorMovieRelationRepository.java +++ b/backend/src/main/java/com/example/backend/model/MovieActorRelationRepository.java @@ -6,6 +6,6 @@ import java.util.List; @Repository -public interface ActorMovieRelationRepository extends JpaRepository { - List findByMovieId(Long movieId); +public interface MovieActorRelationRepository extends JpaRepository { + List findByMovieId(Long movieId); } diff --git a/backend/src/main/java/com/example/backend/service/ActorService.java b/backend/src/main/java/com/example/backend/service/ActorService.java index 30cde2b..534ec0d 100644 --- a/backend/src/main/java/com/example/backend/service/ActorService.java +++ b/backend/src/main/java/com/example/backend/service/ActorService.java @@ -1,8 +1,6 @@ package com.example.backend.service; import com.example.backend.model.Actor; -import com.example.backend.model.ActorMovieRelation; -import com.example.backend.model.ActorMovieRelationRepository; import com.example.backend.model.ActorRepository; import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; diff --git a/backend/src/main/java/com/example/backend/service/ActorMovieService.java b/backend/src/main/java/com/example/backend/service/MovieActorService.java similarity index 72% rename from backend/src/main/java/com/example/backend/service/ActorMovieService.java rename to backend/src/main/java/com/example/backend/service/MovieActorService.java index c3f7106..f2bd066 100644 --- a/backend/src/main/java/com/example/backend/service/ActorMovieService.java +++ b/backend/src/main/java/com/example/backend/service/MovieActorService.java @@ -8,23 +8,23 @@ @Service @RequiredArgsConstructor -public class ActorMovieService { - private final ActorMovieRelationRepository actorMovieRelationRepository; +public class MovieActorService { + private final MovieActorRelationRepository movieActorRelationRepository; private final ActorRepository actorRepository; private final MovieRepository movieRepository; public List getActorsByMovieId(Long movieId) { - return actorMovieRelationRepository.findByMovieId(movieId) + return movieActorRelationRepository.findByMovieId(movieId) .stream() - .map(ActorMovieRelation::getActor) + .map(MovieActorRelation::getActor) .toList(); } public void addActor(Long movieId, Long actorId) { Movie movie = movieRepository.findById(movieId).orElseThrow(); Actor actor = actorRepository.findById(actorId).orElseThrow(); - actorMovieRelationRepository.save(ActorMovieRelation.builder().actor(actor).movie(movie).actor(actor).build()); + movieActorRelationRepository.save(MovieActorRelation.builder().actor(actor).movie(movie).actor(actor).build()); } } diff --git a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java index 8c6de48..51f61e4 100644 --- a/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/ActorControllerTest.java @@ -41,7 +41,7 @@ class ActorControllerTest { private MovieRepository movieRepository; @Autowired - private ActorMovieRelationRepository actorMovieRelationRepository; + private MovieActorRelationRepository movieActorRelationRepository; @Test @DirtiesContext diff --git a/backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java b/backend/src/test/java/com/example/backend/controller/MovieActorControllerTest.java similarity index 78% rename from backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java rename to backend/src/test/java/com/example/backend/controller/MovieActorControllerTest.java index 8388eed..b1ccc01 100644 --- a/backend/src/test/java/com/example/backend/controller/ActorMovieControllerTest.java +++ b/backend/src/test/java/com/example/backend/controller/MovieActorControllerTest.java @@ -20,8 +20,9 @@ @SpringBootTest @AutoConfigureMockMvc -class ActorMovieControllerTest { - private static final String URL_ACTOR_MOVIE_BASE = "/api/actor-movie/{movieId}"; +class MovieActorControllerTest { + private static final String URL_BASE = "/api/movie-actor"; + private static final String URL_WITH_ID = "/api/movie-actor/{movieId}"; private static final String ACTOR_NAME_JANE = "Jane Doe"; private static final String ACTOR_NAME_JIM = "Jim Doe"; @@ -41,7 +42,7 @@ class ActorMovieControllerTest { private ActorRepository actorRepository; @Autowired - private ActorMovieRelationRepository actorMovieRelationRepository; + private MovieActorRelationRepository actorMovieRelationRepository; @Test @DirtiesContext @@ -56,14 +57,14 @@ void getByMovieIdTest_multipleMatch() throws Exception { actorRepository.saveAll(List.of(actorJane, actorJim, actorJoe, actorJohn)); actorMovieRelationRepository.saveAll( List.of( - ActorMovieRelation.builder().actor(actorJane).movie(movieFirst).build(), - ActorMovieRelation.builder().actor(actorJoe).movie(movieSecond).build(), - ActorMovieRelation.builder().actor(actorJim).movie(movieSecond).build(), - ActorMovieRelation.builder().actor(actorJane).movie(movieSecond).build() + MovieActorRelation.builder().actor(actorJane).movie(movieFirst).build(), + MovieActorRelation.builder().actor(actorJoe).movie(movieSecond).build(), + MovieActorRelation.builder().actor(actorJim).movie(movieSecond).build(), + MovieActorRelation.builder().actor(actorJane).movie(movieSecond).build() ) ); - mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, movieSecond.getId())) + mockMvc.perform(MockMvcRequestBuilders.get(URL_WITH_ID, movieSecond.getId())) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath("$", hasSize(3))) .andExpect(jsonPath("$[*].name", containsInAnyOrder( @@ -86,21 +87,21 @@ void getByMovieIdTest_noMatch() throws Exception { actorRepository.saveAll(List.of(actorJane, actorJim, actorJoe, actorJohn)); actorMovieRelationRepository.saveAll( List.of( - ActorMovieRelation.builder().actor(actorJane).movie(movieFirst).build(), - ActorMovieRelation.builder().actor(actorJoe).movie(movieFirst).build(), - ActorMovieRelation.builder().actor(actorJim).movie(movieFirst).build(), - ActorMovieRelation.builder().actor(actorJohn).movie(movieFirst).build() + MovieActorRelation.builder().actor(actorJane).movie(movieFirst).build(), + MovieActorRelation.builder().actor(actorJoe).movie(movieFirst).build(), + MovieActorRelation.builder().actor(actorJim).movie(movieFirst).build(), + MovieActorRelation.builder().actor(actorJohn).movie(movieFirst).build() ) ); - mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, movieSecond.getId())) + mockMvc.perform(MockMvcRequestBuilders.get(URL_WITH_ID, movieSecond.getId())) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(jsonPath("$", hasSize(0))); } @Test void getByMovieIdTest_emptyRequest() throws Exception { - mockMvc.perform(MockMvcRequestBuilders.get(URL_ACTOR_MOVIE_BASE, "")) + mockMvc.perform(MockMvcRequestBuilders.get(URL_WITH_ID, "")) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @@ -112,19 +113,20 @@ void addActorById_successFull() throws Exception { movieRepository.save(movie); actorRepository.save(actor); - mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + mockMvc.perform(MockMvcRequestBuilders.post(URL_BASE) .contentType(MediaType.APPLICATION_JSON) .content( """ { - "id": "%s" + "actorId": "%s", + "movieId": "%s" } - """.formatted(actor.getId()) + """.formatted(actor.getId(), movie.getId()) ) ) .andExpect(MockMvcResultMatchers.status().isOk()); - List actualActorIdList = actorMovieRelationRepository.findByMovieId(movie.getId()); + List actualActorIdList = actorMovieRelationRepository.findByMovieId(movie.getId()); assertEquals(1, actualActorIdList.size()); assertEquals(actor.getId(), actualActorIdList.getFirst().getActor().getId()); } @@ -136,16 +138,17 @@ void addActorById_alreadyAdded() throws Exception { Actor actor = Actor.builder().name(ACTOR_NAME_JANE).build(); movieRepository.save(movie); actorRepository.save(actor); - actorMovieRelationRepository.save(ActorMovieRelation.builder().actor(actor).movie(movie).build()); + actorMovieRelationRepository.save(MovieActorRelation.builder().actor(actor).movie(movie).build()); - mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + mockMvc.perform(MockMvcRequestBuilders.post(URL_BASE) .contentType(MediaType.APPLICATION_JSON) .content( """ { - "id": "%s" + "actorId": "%s", + "movieId": "%s" } - """.formatted(actor.getId()) + """.formatted(actor.getId(), movie.getId()) )) .andExpect(MockMvcResultMatchers.status().is5xxServerError()); } @@ -159,14 +162,15 @@ void addActorById_noSuchActor() throws Exception { actorRepository.save(actor); Long nonExistentActorId = actor.getId() + 1; - mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, movie.getId()) + mockMvc.perform(MockMvcRequestBuilders.post(URL_BASE) .contentType(MediaType.APPLICATION_JSON) .content( """ { - "id": "%s" + "actorId": "%s", + "movieId": "%s", } - """.formatted(nonExistentActorId) + """.formatted(nonExistentActorId, movie.getId()) )) .andExpect(MockMvcResultMatchers.status().is4xxClientError()); } @@ -180,14 +184,15 @@ void addActorById_noSuchMovie() throws Exception { actorRepository.save(actor); Long nonExistentMovieId = movie.getId() + 1L; - mockMvc.perform(MockMvcRequestBuilders.post(URL_ACTOR_MOVIE_BASE, nonExistentMovieId) + mockMvc.perform(MockMvcRequestBuilders.post(URL_BASE) .contentType(MediaType.APPLICATION_JSON) .content( """ { - "id": "%s" + "actorId": "%s", + "movieId": "%s" } - """.formatted(actor.getId()) + """.formatted(actor.getId(), nonExistentMovieId) )) .andExpect(MockMvcResultMatchers.status().is4xxClientError());