Skip to content

Commit

Permalink
test - Album 도메인 단위 테스트 구현
Browse files Browse the repository at this point in the history
1. AlbumControllerV1Test 단위 테스트 구현

2. AlbumServiceTest 단위 테스트 구현

3. AlbumRepositoryTest 단위 테스트 구현
  • Loading branch information
Aram-su committed Sep 4, 2024
1 parent c271831 commit 41262b7
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 41262b7

Please sign in to comment.