Skip to content

Commit

Permalink
Added tests to VideoServiceImpl class and update Spring parent
Browse files Browse the repository at this point in the history
- Updated spring parent version to 3.2.0
- Added more tests to VideoServiceImpl class
  • Loading branch information
LauroSilveira committed Dec 20, 2023
1 parent dcd7c7d commit 75209a5
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 84 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.6</version>
<version>3.2.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
Expand All @@ -36,7 +34,7 @@
@SecurityRequirement(name = "bearer-key")
public class VideoController {

private static final String LOGGIN_PREFIX = "[VideoController]";
private static final String LOGGING_PREFIX = "[VideoController]";

private final VideoService service;

Expand All @@ -47,10 +45,10 @@ public VideoController(final VideoService service) {

@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Page<VideoDto>> getVideos(Pageable pageable) {
log.info("{} Request to get All videos", LOGGIN_PREFIX);
log.info("{} Request to get All videos", LOGGING_PREFIX);
final Page<VideoDto> videos = this.service.getVideos(pageable);
if (videos.hasContent()) {
log.info("{} Response {}: ", LOGGIN_PREFIX, videos);
log.info("{} Response {}: ", LOGGING_PREFIX, videos);
return ResponseEntity.ok().body(videos);
} else {
return ResponseEntity.noContent().build();
Expand All @@ -60,7 +58,7 @@ public ResponseEntity<Page<VideoDto>> getVideos(Pageable pageable) {

@GetMapping("/{id}")
public ResponseEntity<VideoDto> getById(@NotBlank @PathVariable final String id) {
log.info("{} Request to get a video by ID: {}", LOGGIN_PREFIX, id);
log.info("{} Request to get a video by ID: {}", LOGGING_PREFIX, id);
return Optional.ofNullable(service.getById(id))
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
Expand All @@ -70,7 +68,7 @@ public ResponseEntity<VideoDto> getById(@NotBlank @PathVariable final String id)
@PostMapping
public ResponseEntity<VideoDto> save(@Valid @RequestBody final VideoDto dto,
final UriComponentsBuilder uriBuilder) {
log.info("{} Request to Save a new video: {}", LOGGIN_PREFIX, dto);
log.info("{} Request to Save a new video: {}", LOGGING_PREFIX, dto);
final VideoDto videoDto = this.service.save(dto);
//good practices to return the Location in the Header to be search by Id
//return Http code 201 and Localtion with Id
Expand All @@ -81,10 +79,10 @@ public ResponseEntity<VideoDto> save(@Valid @RequestBody final VideoDto dto,
@PutMapping
public ResponseEntity<UpdateVideoDto> update(@Valid @RequestBody final UpdateVideoDto dto,
final UriComponentsBuilder uriBuilder) {
log.info("{} Request to update a video: {}", LOGGIN_PREFIX, dto);
log.info("{} Request to update a video: {}", LOGGING_PREFIX, dto);
final var videoDto = this.service.updateMovie(dto);
//good practices to return the Location in the Header to be search by Id
//return Http code 201 and Localtion with Id
//return Http code 201 and Location with Id
return ResponseEntity.created(uriBuilder.path("/videos/{id}")
.buildAndExpand(videoDto.id())
.toUri()).body(videoDto);
Expand All @@ -93,16 +91,16 @@ public ResponseEntity<UpdateVideoDto> update(@Valid @RequestBody final UpdateVid
@DeleteMapping("/{id}")
@Secured("ROLE_ADMIN")
public ResponseEntity<VideoDto> delete(@NotBlank @PathVariable final String id) {
log.info("{} Request to Delete a video by ID: {}", LOGGIN_PREFIX, id);
log.info("{} Request to Delete a video by ID: {}", LOGGING_PREFIX, id);
final Optional<VideoDto> dto = this.service.delete(id);
return dto.map(videoDto -> ResponseEntity.status(HttpStatus.NO_CONTENT).body(videoDto))
.orElseGet(() -> ResponseEntity.noContent().build());
}

@GetMapping("/search")
@GetMapping("/title")
public ResponseEntity<List<VideoDto>> getVideosByTitle(
@NotBlank @RequestParam("title") final String title) {
log.info("{} Request to get a video by title: {}", LOGGIN_PREFIX, title);
log.info("{} Request to get a video by title: {}", LOGGING_PREFIX, title);
final var videosByTitle = this.service.getVideosByTitle(title);
if (videosByTitle.isEmpty()) {
return ResponseEntity.noContent().build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import java.util.Arrays;
import java.util.List;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
package com.alura.aluraflixapi.controller;

import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.alura.aluraflixapi.domain.category.Rating;
import com.alura.aluraflixapi.domain.category.dto.CategoryDto;
import com.alura.aluraflixapi.domain.video.dto.UpdateVideoDto;
Expand All @@ -19,43 +12,47 @@
import com.alura.aluraflixapi.infraestructure.service.CategoryService;
import com.alura.aluraflixapi.infraestructure.service.UserService;
import com.alura.aluraflixapi.infraestructure.service.VideoServiceImpl;
import com.alura.aluraflixapi.jsonutils.ParseJson;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.*;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;


@ExtendWith(SpringExtension.class)
//@WebMvcTest: Includes both the @AutoConfigureWebMvc and the @AutoConfigureMockMvc, among other functionality.
@WebMvcTest
//this annotation can be replaced at each test method scope
@WithMockUser(value = "admin", username = "admin", password = "admin", roles = "ADMIN")
class VideoControllerTest {
class VideoControllerTest extends ParseJson {

private static final String PREFIX_PATH = "/video/";

private static ObjectMapper mapper;

Expand Down Expand Up @@ -105,13 +102,15 @@ static void setup() {
}

@Test
@DisplayName("Should return all videos and response 200 OK")
void get_all_videos_test() throws Exception {
//Given
final List<VideoDto> videos = buildVideosDto();
final var jsonFile = getJsonFile(PREFIX_PATH + "getAllVideos_response_ok.json");
final var videosExpect = Arrays.stream(parseToJavaObject(jsonFile, VideoDto[].class)).toList();
//Workaround to fix JsonSerialize on Spring boot version 3.2.0
final var pageable = PageRequest.of(0, 10);
when(this.videoService.getVideos(Mockito.any()))
.thenReturn(new PageImpl<>(videos, pageable, videos.size()));
.thenReturn(new PageImpl<>(videosExpect, pageable, videosExpect.size()));

final MvcResult response = this.mockMvc.perform(MockMvcRequestBuilders.get("/videos")
.contentType(MediaType.APPLICATION_JSON))
Expand All @@ -124,38 +123,54 @@ void get_all_videos_test() throws Exception {
class));
//Then
assertNotNull(videosDtos);
assertEquals(4, videosDtos.size());
assertEquals(videosExpect.size(), videosDtos.size());
}

@Test
@DisplayName("Should not return all videos and response No Content")
void get_all_videos_response_no_content_test() throws Exception {
//Given
when(this.videoService.getVideos(Mockito.any()))
.thenReturn(Page.empty());

//Then
this.mockMvc.perform(MockMvcRequestBuilders.get("/videos")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().is2xxSuccessful());
}

@Test
@DisplayName("Should return a video by Id and response 200 OK")
void get_video_by_id() throws Exception {

//Given
final VideoDto request = buildVideosDto().get(0);

final var jsonFile = getJsonFile(PREFIX_PATH + "getById_video_response_ok.json");
final var videoDto = parseToJavaObject(jsonFile, VideoDto.class);
when(this.videoService.getById(Mockito.anyString()))
.thenReturn(request);
.thenReturn(videoDto);

//When
final MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get("/videos/{id}", "1")
final MvcResult mvcResult = this.mockMvc.perform(MockMvcRequestBuilders.get("/videos/{id}", "63680c011892283477b3e9b9")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().is2xxSuccessful())
.andReturn();

//Then
VideoDto videoDto = mapper.readValue(mvcResult.getResponse().getContentAsString(),
VideoDto response = mapper.readValue(mvcResult.getResponse().getContentAsString(),
VideoDto.class);

assertNotNull(videoDto);
assertAll(() -> assertEquals(request.id(), videoDto.id()),
() -> Assertions.assertEquals(request.url(), videoDto.url()),
() -> Assertions.assertEquals(request.description(), videoDto.description()),
() -> Assertions.assertEquals(request.title(), videoDto.title())
assertAll(() -> assertEquals(response.id(), videoDto.id()),
() -> Assertions.assertEquals(response.url(), videoDto.url()),
() -> Assertions.assertEquals(response.description(), videoDto.description()),
() -> Assertions.assertEquals(response.title(), videoDto.title())
);
}

@Test
@DisplayName("Should create a new Video and response 200 OK")
void save_a_new_video_test() throws Exception {

//Given
Expand Down Expand Up @@ -189,15 +204,11 @@ void save_a_new_video_test() throws Exception {
}

@Test
@DisplayName("Should update a video by Id and return 200 OK")
void update_video_by_id_test() throws Exception {

//Given
final var videoToUpdate =
new UpdateVideoDto(UUID.randomUUID().toString(),
"Hobbit: La batalla de los cincos ejercitos", "La batalla de los cincos ejercitos",
"www.thehobbit2.com",
new CategoryDto(UUID.randomUUID().toString(), Rating.FANTASY.name(), "Fantasy",
"#FFD700"));
final var jsonFile = getJsonFile(PREFIX_PATH + "getById_video_response_ok.json");
final var videoToUpdate = parseToJavaObject(jsonFile, UpdateVideoDto.class);

when(this.videoService.updateMovie(Mockito.any()))
.thenReturn(videoToUpdate);
Expand Down Expand Up @@ -229,6 +240,7 @@ void update_video_by_id_test() throws Exception {
}

@Test
@DisplayName("Should allow delete a video by id and response No Content")
void delete_video_by_id_test() throws Exception {

//Given
Expand All @@ -241,38 +253,42 @@ void delete_video_by_id_test() throws Exception {
.andExpect(status().isNoContent());
}

@Test
@DisplayName("Should return a list of videos searched by title response OK")
void getVideosByTitle_test() throws Exception {
//Given
final var jsonFile = getJsonFile(PREFIX_PATH + "getVideoByTitle_response_ok.json");
final var videosByTitleExpected = Arrays.stream(parseToJavaObject(jsonFile, VideoDto[].class)).toList();
when(this.videoService.getVideosByTitle(Mockito.anyString()))
.thenReturn(videosByTitleExpected);

final MvcResult response = this.mockMvc.perform(MockMvcRequestBuilders.get("/videos/title")
.param("title", "The Hobbit - The battle of five armies")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isFound())
.andReturn();

//Then
assertNotNull(response);
final var videosByTitleResponse = Arrays.stream(mapper.readValue(response.getResponse().getContentAsString(),
VideoDto[].class)).toList();
org.assertj.core.api.Assertions.assertThat(videosByTitleResponse).usingRecursiveComparison()
.isEqualTo(videosByTitleExpected);
}

@Test
@DisplayName("Should not return a list of videos searched by title response No Content")
void getVideosByTitle_response_no_content_test() throws Exception {
//Given
when(this.videoService.getVideosByTitle(Mockito.anyString()))
.thenReturn(List.of());

private static List<VideoDto> buildVideosDto() {
final var categoryDto = new CategoryDto(UUID.randomUUID().toString(), Rating.FREE.name(),
"Fantasy", "#FFD700");
return List.of(VideoDto.builder()
.id(UUID.randomUUID().toString())
.title("Lord of the rings - fellowship of the ring")
.description("Lord of the rings - fellowship of the ring")
.url("http://www.lordoftherings.com")
.category(categoryDto)
.build(),
VideoDto.builder()
.id(UUID.randomUUID().toString())
.title("Lord of the rings - return of the king")
.description("Lord of the rings - return of the king")
.url("http://www.lordoftherings.com")
.category(categoryDto)
.build(),
VideoDto.builder()
.id(UUID.randomUUID().toString())
.title("Lord of the rings - The Two towers")
.description("Lord of the rings - The Two towers")
.url("http://www.lordoftherings.com")
.category(categoryDto)
.build(),
VideoDto.builder()
.id(UUID.randomUUID().toString())
.title("The hobbit - unnespect adventure")
.description("The hobbit - unnespect adventure")
.url("http://www.thehobbit.com")
.category(categoryDto)
.build()
);
final MvcResult response = this.mockMvc.perform(MockMvcRequestBuilders.get("/videos/title")
.param("title", "The Hobbit - The battle of five armies")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isNoContent())
.andReturn();
}
}
14 changes: 14 additions & 0 deletions src/test/resources/json/video/getVideoByTitle_response_ok.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[
{
"id": "63680c011892283477b3e9b9",
"title": "The Hobbit - The battle of Five armies",
"description": "best movie ever",
"url": "https://theHobbitThebattleofivearmies.com",
"category": {
"id": "63f67ec16295ed744dd460cd",
"rating": "FREE",
"title": "Fantasy",
"colorHex": "#ffff83"
}
}
]

0 comments on commit 75209a5

Please sign in to comment.