Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added tests to VideoServiceImpl class and update Spring parent #89

Merged
merged 1 commit into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"
}
}
]