Skip to content

Commit

Permalink
Merge pull request #47 from NU-BIM/test/album
Browse files Browse the repository at this point in the history
Album 도메인 단위 테스트 구현
  • Loading branch information
Aram-su authored Sep 5, 2024
2 parents 4546c80 + 41262b7 commit 226c05f
Show file tree
Hide file tree
Showing 3 changed files with 682 additions and 0 deletions.
379 changes: 379 additions & 0 deletions src/test/java/com/soyeon/nubim/domain/album/AlbumControllerV1Test.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,379 @@
package com.soyeon.nubim.domain.album;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.soyeon.nubim.domain.album.dto.AlbumCreateRequestDto;
import com.soyeon.nubim.domain.album.dto.AlbumCreateResponseDto;
import com.soyeon.nubim.domain.album.dto.AlbumReadResponseDto;
import com.soyeon.nubim.domain.album.dto.AlbumUpdateRequestDto;
import com.soyeon.nubim.domain.album.dto.LocationCreateRequestDto;
import com.soyeon.nubim.domain.album.dto.LocationCreateResponseDto;
import com.soyeon.nubim.domain.album.dto.LocationReadResponseDto;
import com.soyeon.nubim.domain.album.dto.LocationUpdateRequestDto;
import com.soyeon.nubim.domain.album.exception.AlbumNotFoundException;
import com.soyeon.nubim.domain.user.exception.UserNotFoundException;
import com.soyeon.nubim.security.SecurityConfig;
import com.soyeon.nubim.security.jwt.JwtAuthenticationFilter;
import com.soyeon.nubim.security.jwt.JwtTokenProvider;

@WebMvcTest(controllers = AlbumControllerV1.class)
@Import({SecurityConfig.class, JwtAuthenticationFilter.class, JwtTokenProvider.class})
@TestPropertySource(properties = {
"jwt.secret=testsecretkeytestsecretkeytestsecretkeytestsecretkey",
"logging.level.com.soyeon.nubim=DEBUG",
})
class AlbumControllerV1Test {

@Autowired
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;

@Autowired
private ObjectMapper objectMapper;
@MockBean
private AlbumService albumService;
@MockBean
private AlbumPhotoUploadUrlService albumPhotoUploadUrlService;

@Autowired
private JwtTokenProvider jwtTokenProvider;

@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;

private AlbumCreateRequestDto createRequestDto;
private AlbumCreateResponseDto createResponseDto;
private AlbumReadResponseDto readResponseDto;
private AlbumUpdateRequestDto updateRequestDto;

private String accessToken;

@BeforeEach
void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
.addFilter(new CharacterEncodingFilter("UTF-8", true))
.addFilter(jwtAuthenticationFilter)
.alwaysDo(print())
.build();

accessToken = jwtTokenProvider.generateAccessToken("1L", "testUser@email.com", "USER");

Long albumId = 1L;
Long userId = 1L;
String description = "create album test";
Map<Integer, String> photoUrls = Map.of(1, "https://test01.jpg",
2, "https://test02.jpg",
3, "https://test03.jpg",
4, "https://test04.jpg");

List<LocationCreateRequestDto> locationsRequest = List.of(
LocationCreateRequestDto.builder()
.latitude(37.5665)
.longitude(126.9780)
.visitedAt(LocalDateTime.now())
.placeName("서울")
.build(),
LocationCreateRequestDto.builder()
.latitude(35.1796)
.longitude(129.0756)
.visitedAt(LocalDateTime.now().minusDays(1))
.placeName("서울")
.build(),
LocationCreateRequestDto.builder()
.latitude(33.4996)
.longitude(126.5312)
.visitedAt(LocalDateTime.now().minusDays(2))
.placeName("서울")
.build()
);

List<LocationCreateResponseDto> locationsResponse = List.of(
LocationCreateResponseDto.builder()
.locationId(1L)
.albumId(1L)
.latitude(37.5665)
.longitude(126.9780)
.visitedAt(LocalDateTime.now())
.placeName("서울")
.build(),
LocationCreateResponseDto.builder()
.locationId(2L)
.albumId(1L)
.latitude(35.1796)
.longitude(129.0756)
.visitedAt(LocalDateTime.now().minusDays(1))
.placeName("서울")
.build(),
LocationCreateResponseDto.builder()
.locationId(3L)
.albumId(1L)
.latitude(33.4996)
.longitude(126.5312)
.visitedAt(LocalDateTime.now().minusDays(2))
.placeName("서울")
.build()
);

createRequestDto = AlbumCreateRequestDto.builder()
.description(description)
.photoUrls(photoUrls)
.locations(locationsRequest)
.build();

createResponseDto = AlbumCreateResponseDto.builder()
.albumId(albumId)
.userId(userId)
.description(description)
.photoUrls(photoUrls)
.locations(locationsResponse)
.build();

readResponseDto = AlbumReadResponseDto.builder()
.albumId(albumId)
.userId(1L)
.description("read album test")
.photoUrls(Map.of(1, "https://test01.jpg", 2, "https://test02.jpg"))
.locations(List.of(
LocationReadResponseDto.builder()
.locationId(1L)
.albumId(albumId)
.latitude(37.5665)
.longitude(126.9780)
.visitedAt(LocalDateTime.now())
.placeName("서울")
.build()
))
.build();

updateRequestDto = AlbumUpdateRequestDto.builder()
.description("update album test")
.photoUrls(Map.of(1, "https://change01.jpg", 2, "https://change01.jpg"))
.locations(List.of(
LocationUpdateRequestDto.builder()
.latitude(1.0)
.longitude(2.0)
.visitedAt(LocalDateTime.now())
.placeName("경기도")
.build())
)
.build();
}

@Test
@DisplayName("앨범 생성 - 성공 case")
void createAlbum() throws Exception {
when(albumService.createAlbum(any(AlbumCreateRequestDto.class))).thenReturn(createResponseDto);

MvcResult result = mockMvc.perform(post("/v1/albums")
.header("Authorization", "Bearer " + accessToken)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(createRequestDto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.albumId").value(createResponseDto.getAlbumId()))
.andExpect(jsonPath("$.description").value(createResponseDto.getDescription()))
.andExpect(jsonPath("$.photoUrls").isNotEmpty())
.andExpect(jsonPath("$.locations").isNotEmpty())
.andReturn();

String content = result.getResponse().getContentAsString();
AlbumCreateResponseDto actualCreateResponseDto = objectMapper.readValue(content, AlbumCreateResponseDto.class);

assertEquals(createResponseDto.getPhotoUrls().size(), actualCreateResponseDto.getPhotoUrls().size());
for (Map.Entry<Integer, String> photoUrl : createResponseDto.getPhotoUrls().entrySet()) {
assertEquals(photoUrl.getValue(), actualCreateResponseDto.getPhotoUrls().get(photoUrl.getKey()));
}

assertEquals(createResponseDto.getLocations().size(), actualCreateResponseDto.getLocations().size());
for (int i = 0; i < createResponseDto.getLocations().size(); i++) {
LocationCreateResponseDto expectedLocation = createResponseDto.getLocations().get(i);
LocationCreateResponseDto actualLocation = actualCreateResponseDto.getLocations().get(i);

assertEquals(expectedLocation.getLatitude(), actualLocation.getLatitude());
assertEquals(expectedLocation.getLongitude(), actualLocation.getLongitude());
assertEquals(expectedLocation.getVisitedAt(), actualLocation.getVisitedAt());
assertEquals(expectedLocation.getPlaceName(), actualLocation.getPlaceName());
}
}

@Test
@DisplayName("앨범 생성 - 실패 case : access token 이 없는 경우")
void createAlbum_Unauthorized() throws Exception {
when(albumService.createAlbum(any(AlbumCreateRequestDto.class))).thenReturn(createResponseDto);

mockMvc.perform(post("/v1/albums")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(createRequestDto)))
.andExpect(status().isUnauthorized());
}

@Test
@DisplayName("앨범 검색 - 성공 case")
void getAlbumWithLocations() throws Exception {
Long albumId = 1L;

when(albumService.findByIdWithLocations(albumId)).thenReturn(readResponseDto);

mockMvc.perform(get("/v1/albums/{albumId}", albumId)
.header("Authorization", "Bearer " + accessToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$.userId").value(readResponseDto.getUserId()))
.andExpect(jsonPath("$.albumId").value(albumId))
.andExpect(jsonPath("$.description").value(readResponseDto.getDescription()))
.andExpect(jsonPath("$.photoUrls").isNotEmpty())
.andExpect(jsonPath("$.locations").isNotEmpty())
.andExpect(
jsonPath("$.locations[0].placeName").value(readResponseDto.getLocations().get(0).getPlaceName()));

verify(albumService).findByIdWithLocations(albumId);
}

@Test
@DisplayName("앨범 검색 - 실패 case : 존재 하지 않는 앨범 ID 검색")
void getAlbumWithLocations_NotFound() throws Exception {
Long albumId = 999L;

when(albumService.findByIdWithLocations(albumId)).thenThrow(new AlbumNotFoundException(albumId));

mockMvc.perform(get("/v1/albums/{albumId}", albumId)
.header("Authorization", "Bearer " + accessToken))
.andExpect(status().isNotFound());

verify(albumService).findByIdWithLocations(albumId);
}

@Test
@DisplayName("닉네임으로 앨범 검색 - 성공 case")
void getUserAlbums() throws Exception {
String nickname = "testUser";

when(albumService.findAlbumsByUserNickname(nickname)).thenReturn(List.of(readResponseDto));

MvcResult result = mockMvc.perform(get("/v1/albums/user/{nickname}", nickname)
.header("Authorization", "Bearer " + accessToken))
.andExpect(status().isOk())
.andReturn();

String content = result.getResponse().getContentAsString();
List<AlbumReadResponseDto> actualAlbums
= objectMapper.readValue(content, new TypeReference<>() {});

assertEquals(1, actualAlbums.size());
assertEquals(readResponseDto.getAlbumId(), actualAlbums.get(0).getAlbumId());
assertEquals(readResponseDto.getDescription(), actualAlbums.get(0).getDescription());
assertEquals(readResponseDto.getPhotoUrls().size(), actualAlbums.get(0).getPhotoUrls().size());
for (Map.Entry<Integer, String> photoUrl : readResponseDto.getPhotoUrls().entrySet()) {
assertEquals(photoUrl.getValue(), actualAlbums.get(0).getPhotoUrls().get(photoUrl.getKey()));
}

assertEquals(readResponseDto.getLocations().size(), actualAlbums.get(0).getLocations().size());
for (int i = 0; i < readResponseDto.getLocations().size(); i++) {
LocationReadResponseDto expectedLocation = readResponseDto.getLocations().get(i);
LocationReadResponseDto actualLocation = actualAlbums.get(0).getLocations().get(i);
assertEquals(expectedLocation.getLatitude(), actualLocation.getLatitude());
assertEquals(expectedLocation.getLongitude(), actualLocation.getLongitude());
assertEquals(expectedLocation.getVisitedAt(), actualLocation.getVisitedAt());
assertEquals(expectedLocation.getPlaceName(), actualLocation.getPlaceName());
}
}

@Test
@DisplayName("닉네임으로 앨범 검색 - 실패 case : 존재하지 않는 닉네임")
void getUserAlbums_NotFound() throws Exception {
String nickname = "testUser";

when(albumService.findAlbumsByUserNickname(nickname)).thenThrow(
new UserNotFoundException(nickname, "nickname"));

mockMvc.perform(get("/v1/albums/user/{nickname}", nickname)
.header("Authorization", "Bearer " + accessToken))
.andExpect(status().isNotFound());
}

@Test
@DisplayName("앨범 업데이트 - 성공 case")
void updateAlbum() throws Exception {
Long albumId = 1L;

List<LocationUpdateRequestDto> locationUpdateList = updateRequestDto.getLocations();
List<LocationReadResponseDto> locationReadList = new ArrayList<>(locationUpdateList.size());
for (int i = 0; i < locationUpdateList.size(); i++) {
LocationUpdateRequestDto locationUpdateRequest = locationUpdateList.get(i);
locationReadList.add(LocationReadResponseDto.builder()
.locationId((long)(i + 1))
.albumId(albumId)
.longitude(locationUpdateRequest.getLongitude())
.latitude(locationUpdateRequest.getLatitude())
.visitedAt(locationUpdateRequest.getVisitedAt())
.placeName(locationUpdateRequest.getPlaceName())
.build());
}

AlbumReadResponseDto updateResponseDto = AlbumReadResponseDto.builder()
.albumId(readResponseDto.getAlbumId())
.userId(readResponseDto.getUserId())
.description(updateRequestDto.getDescription())
.photoUrls(updateRequestDto.getPhotoUrls())
.locations(locationReadList)
.build();

when(albumService.updateAlbum(any(Long.class), any(AlbumUpdateRequestDto.class))).thenReturn(updateResponseDto);

MvcResult result = mockMvc.perform(put("/v1/albums/{albumId}", albumId)
.header("Authorization", "Bearer " + accessToken)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(updateRequestDto)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.albumId").value(albumId))
.andExpect(jsonPath("$.userId").value(readResponseDto.getUserId()))
.andExpect(jsonPath("$.description").value(updateRequestDto.getDescription()))
.andExpect(jsonPath("$.photoUrls").isNotEmpty())
.andExpect(jsonPath("$.locations").isNotEmpty())
.andReturn();

String content = result.getResponse().getContentAsString();
AlbumReadResponseDto actualReadResponseDto = objectMapper.readValue(content, AlbumReadResponseDto.class);

for (Map.Entry<Integer, String> photoUrl : updateRequestDto.getPhotoUrls().entrySet()) {
assertEquals(photoUrl.getValue(), actualReadResponseDto.getPhotoUrls().get(photoUrl.getKey()));
}

assertEquals(updateRequestDto.getLocations().size(), actualReadResponseDto.getLocations().size());
for (int i = 0; i < updateRequestDto.getLocations().size(); i++) {
LocationUpdateRequestDto expectedLocation = updateRequestDto.getLocations().get(i);
LocationReadResponseDto actualLocation = actualReadResponseDto.getLocations().get(i);

assertEquals(expectedLocation.getLatitude(), actualLocation.getLatitude());
assertEquals(expectedLocation.getLongitude(), actualLocation.getLongitude());
assertEquals(expectedLocation.getVisitedAt(), actualLocation.getVisitedAt());
assertEquals(expectedLocation.getPlaceName(), actualLocation.getPlaceName());
}
}

}
Loading

0 comments on commit 226c05f

Please sign in to comment.