최신글
hyeonga_code
Project_05_Url 조회 기능 구현 /TestCode 본문
반응형
Url 조회 기능
1. UrlController
> 기존 코드
더보기
package com.hyeongarl.controller;
import com.hyeongarl.config.jwt.TokenProvider;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.Url;
import com.hyeongarl.service.UrlService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@RequestMapping("/url")
public class UrlController {
private final TokenProvider tokenProvider;
private final UrlService urlService;
/**
* Url 등록
* @param urlRequest 입력받은 url 정보
* @return 저장된 url 정보
*/
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public UrlResponseDto saveUrl(@RequestBody UrlRequestDto urlRequest) {
Url saveUrl = urlRequest.toEntity();
saveUrl.setUserId(1L);
return UrlResponseDto.fromEntity(urlService.save(saveUrl));
}
}
> 작성 코드
/**
* Url 단건 조회
* @param urlId 조회할 Url Id
* @return 조죄한 url 정보
*/
@GetMapping("/{urlId}")
public UrlResponseDto getUrl(@PathVariable Long urlId) {
return UrlResponseDto.fromEntity(urlService.getUrl(urlId));
}
> 전체 코드
더보기
package com.hyeongarl.controller;
import com.hyeongarl.config.jwt.TokenProvider;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.Url;
import com.hyeongarl.service.UrlService;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@RequestMapping("/url")
public class UrlController {
private final TokenProvider tokenProvider;
private final UrlService urlService;
/**
* Url 등록
* @param urlRequest 입력받은 url 정보
* @return 저장된 url 정보
*/
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public UrlResponseDto saveUrl(@RequestBody UrlRequestDto urlRequest) {
Url saveUrl = urlRequest.toEntity();
saveUrl.setUserId(1L);
return UrlResponseDto.fromEntity(urlService.save(saveUrl));
}
/**
* Url 단건 조회
* @param urlId 조회할 Url Id
* @return 조죄한 url 정보
*/
@GetMapping("/{urlId}")
public UrlResponseDto getUrl(@PathVariable Long urlId) {
return UrlResponseDto.fromEntity(urlService.getUrl(urlId));
}
}
2. UrlService
> 기존 코드
더보기
package com.hyeongarl.service;
import com.hyeongarl.entity.Url;
import com.hyeongarl.error.UrlAlreadyExistException;
import com.hyeongarl.error.UrlInvalidException;
import com.hyeongarl.error.UrlNotFoundException;
import com.hyeongarl.repository.UrlRepository;
import com.hyeongarl.util.UrlValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UrlService {
private final UrlRepository urlRepository;
/**
* Url 등록
* @param url 입력한 Url 정보
* @return 저장된 url 정보
*/
public Url save(Url url) {
// url 유효성 검사
if(!UrlValidator.checkUrl(url.getUrl())) {
throw new UrlInvalidException();
}
// 이미 존재하는 정보(사용자, url())
if(urlRepository.existsByUrl(url.getUrl())) {
throw new UrlAlreadyExistException();
}
return urlRepository.save(url);
}
}
> 작성 코드
/**
* Url 단건 조회
* @param urlId 조회할 Url Id
* @return 조회한 url 정보
*/
public Url getUrl(Long urlId) {
return urlRepository.findById(urlId).orElseThrow(UrlNotFoundException::new);
}
> 전체 코드
더보기
package com.hyeongarl.service;
import com.hyeongarl.entity.Url;
import com.hyeongarl.error.UrlAlreadyExistException;
import com.hyeongarl.error.UrlInvalidException;
import com.hyeongarl.error.UrlNotFoundException;
import com.hyeongarl.repository.UrlRepository;
import com.hyeongarl.util.UrlValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class UrlService {
private final UrlRepository urlRepository;
/**
* Url 등록
* @param url 입력한 Url 정보
* @return 저장된 url 정보
*/
public Url save(Url url) {
// url 유효성 검사
if(!UrlValidator.checkUrl(url.getUrl())) {
throw new UrlInvalidException();
}
// 이미 존재하는 정보(사용자, url())
if(urlRepository.existsByUrl(url.getUrl())) {
throw new UrlAlreadyExistException();
}
return urlRepository.save(url);
}
/**
* Url 단건 조회
* @param urlId 조회할 Url Id
* @return 조회한 url 정보
*/
public Url getUrl(Long urlId) {
return urlRepository.findById(urlId).orElseThrow(UrlNotFoundException::new);
}
}
UrlServiceTest
> 기존 코드
더보기
package com.hyeongarl.service;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.entity.Url;
import com.hyeongarl.error.UrlAlreadyExistException;
import com.hyeongarl.error.UrlInvalidException;
import com.hyeongarl.error.UrlNotFoundException;
import com.hyeongarl.repository.UrlRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
/*
@ExtendWith(MockitoExtension.class)
JUnit5의 확장 모델을 활용하여 Mockito를 사용할 수 있다.
MockExtension : Mockito에 대한 설정을 초기화 및 @Mockito 처리
*/
@ExtendWith(MockitoExtension.class)
public class UrlServiceTest {
/*
@Mock
Mockito를 사용해 가짜 객체를 생성
*/
@Mock
private UrlRepository urlRepository;
/*
@InjectMocks
실제 객체로 만들어 필요한 의존성 객체를 주입
*/
@InjectMocks
private UrlService urlService;
@Test
@DisplayName("save_success")
void saveUrl_success() {
UrlRequestDto urlRequest = new UrlRequestDto("https://www.naver.com", "saveUrlTitle", "saveUrl_Description", 1L);
when(urlRepository.existsByUrl(urlRequest.getUrl())).thenReturn(false);
when(urlRepository.save(any(Url.class))).thenReturn(urlRequest.toEntity());
Url url = urlService.save(urlRequest.toEntity());
assertNotNull(url);
assertEquals(urlRequest.getUrl(), url.getUrl());
assertEquals(urlRequest.getUrlTitle(), url.getUrlTitle());
assertEquals(urlRequest.getUrlDescription(), url.getUrlDescription());
verify(urlRepository, times(1)).save(any(Url.class));
}
@Test
@DisplayName("save_fail_invalid")
void saveUrl_fail_invalid() {
UrlRequestDto urlRequest = new UrlRequestDto(null, "saveUrlTitle", "saveUrlDescription", 1L);
assertThrows(UrlInvalidException.class, () -> urlService.save(urlRequest.toEntity()));
verify(urlRepository, never()).save(any(Url.class));
}
@Test
@DisplayName("save_fail_alreadyExist")
void saveUrl_fail_alreadyExist() {
UrlRequestDto urlRequest = new UrlRequestDto("https://www.naver.com", "saveUrlTitle", "saveUrl_Description", 1L);
when(urlRepository.existsByUrl(urlRequest.getUrl())).thenReturn(true);
assertThrows(UrlAlreadyExistException.class, ()-> urlService.save(urlRequest.toEntity()));
verify(urlRepository, never()).save(any(Url.class));
}
}
> 작성 코드
@Test
@DisplayName("get_success")
void getUrl_success() {
Url url = new Url(1L, "http://getUrl.com",
"getUrl Title", "getUrl Description",
1L, 1L, null, null);
when(urlRepository.findById(url.getUrlId())).thenReturn(Optional.of(url));
Url result = urlService.getUrl(1L);
assertNotNull(result);
assertEquals(url.getUrl(), result.getUrl());
verify(urlRepository, times(1)).findById(any(Long.class));
}
@Test
@DisplayName("get_fail_notFound")
void getUrl_fail_notFound() {
when(urlRepository.findById(any(Long.class))).thenReturn(Optional.empty());
assertThrows(UrlNotFoundException.class, () -> urlService.getUrl(any(Long.class)));
verify(urlRepository, times(1)).findById(any(Long.class));
}
> 전체 코드
더보기
package com.hyeongarl.service;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.entity.Url;
import com.hyeongarl.error.UrlAlreadyExistException;
import com.hyeongarl.error.UrlInvalidException;
import com.hyeongarl.error.UrlNotFoundException;
import com.hyeongarl.repository.UrlRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
/*
@ExtendWith(MockitoExtension.class)
JUnit5의 확장 모델을 활용하여 Mockito를 사용할 수 있다.
MockExtension : Mockito에 대한 설정을 초기화 및 @Mockito 처리
*/
@ExtendWith(MockitoExtension.class)
public class UrlServiceTest {
/*
@Mock
Mockito를 사용해 가짜 객체를 생성
*/
@Mock
private UrlRepository urlRepository;
/*
@InjectMocks
실제 객체로 만들어 필요한 의존성 객체를 주입
*/
@InjectMocks
private UrlService urlService;
@Test
@DisplayName("save_success")
void saveUrl_success() {
UrlRequestDto urlRequest = new UrlRequestDto("https://www.naver.com", "saveUrlTitle", "saveUrl_Description", 1L);
when(urlRepository.existsByUrl(urlRequest.getUrl())).thenReturn(false);
when(urlRepository.save(any(Url.class))).thenReturn(urlRequest.toEntity());
Url url = urlService.save(urlRequest.toEntity());
assertNotNull(url);
assertEquals(urlRequest.getUrl(), url.getUrl());
assertEquals(urlRequest.getUrlTitle(), url.getUrlTitle());
assertEquals(urlRequest.getUrlDescription(), url.getUrlDescription());
verify(urlRepository, times(1)).save(any(Url.class));
}
@Test
@DisplayName("save_fail_invalid")
void saveUrl_fail_invalid() {
UrlRequestDto urlRequest = new UrlRequestDto(null, "saveUrlTitle", "saveUrlDescription", 1L);
assertThrows(UrlInvalidException.class, () -> urlService.save(urlRequest.toEntity()));
verify(urlRepository, never()).save(any(Url.class));
}
@Test
@DisplayName("save_fail_alreadyExist")
void saveUrl_fail_alreadyExist() {
UrlRequestDto urlRequest = new UrlRequestDto("https://www.naver.com", "saveUrlTitle", "saveUrl_Description", 1L);
when(urlRepository.existsByUrl(urlRequest.getUrl())).thenReturn(true);
assertThrows(UrlAlreadyExistException.class, ()-> urlService.save(urlRequest.toEntity()));
verify(urlRepository, never()).save(any(Url.class));
}
@Test
@DisplayName("get_success")
void getUrl_success() {
Url url = new Url(1L, "http://getUrl.com",
"getUrl Title", "getUrl Description",
1L, 1L, null, null);
when(urlRepository.findById(url.getUrlId())).thenReturn(Optional.of(url));
Url result = urlService.getUrl(1L);
assertNotNull(result);
assertEquals(url.getUrl(), result.getUrl());
verify(urlRepository, times(1)).findById(any(Long.class));
}
@Test
@DisplayName("get_fail_notFound")
void getUrl_fail_notFound() {
when(urlRepository.findById(any(Long.class))).thenReturn(Optional.empty());
assertThrows(UrlNotFoundException.class, () -> urlService.getUrl(any(Long.class)));
verify(urlRepository, times(1)).findById(any(Long.class));
}
}
> 실행
@Nested
@DisplayName("getUrlTest")
class getUrlTests {
@Test
@DisplayName("get_success")
void getUrl_success() {
Url url = new Url(1L, "http://getUrl.com",
"getUrl Title", "getUrl Description",
1L, 1L, null, null);
when(urlRepository.findById(url.getUrlId())).thenReturn(Optional.of(url));
Url result = urlService.getUrl(1L);
assertNotNull(result);
assertEquals(url.getUrl(), result.getUrl());
verify(urlRepository, times(1)).findById(any(Long.class));
}
@Test
@DisplayName("get_fail_notFound")
void getUrl_fail_notFound() {
when(urlRepository.findById(any(Long.class))).thenReturn(Optional.empty());
assertThrows(UrlNotFoundException.class, () -> urlService.getUrl(any(Long.class)));
verify(urlRepository, times(1)).findById(any(Long.class));
}
}
Test중 관련된 테스트만 실행하기 위해 @Nested(import org.junit.jupiter.api.Nested) 로 묶어 실행했다.
UrlControllerTest
> 기존 코드
더보기
package com.hyeongarl.controller;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.Url;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UrlControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
@DisplayName("testSaveUrl")
void testSaveUrl() {
UrlRequestDto urlRequest = UrlRequestDto.builder()
.url("https://www.naver.com")
.urlTitle("saveUrlTitle")
.urlDescription("saveUrlDescription")
.categoryId(1L)
.build();
ResponseEntity<UrlResponseDto> responseEntity
= restTemplate.postForEntity("/url", urlRequest, UrlResponseDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.CREATED);
UrlResponseDto responseBody = responseEntity.getBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.getUrl()).isEqualTo("https://www.naver.com");
}
}
> 작성 코드
@Test
@DisplayName("testGetUrl")
void testGetUrl() {
Url url = new Url(1L, "https://www.naver.com",
"getUrl Title", "getUrl Description",
1L, 1L, null, null);
ResponseEntity<UrlResponseDto> saveEntity
= restTemplate.postForEntity("/url", url, UrlResponseDto.class);
ResponseEntity<UrlResponseDto> responseEntity
= restTemplate.getForEntity("/url/1", UrlResponseDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
UrlResponseDto responseBody = responseEntity.getBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.getUrlId()).isEqualTo(1L);
}
> 전체 코드
더보기
package com.hyeongarl.controller;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.Url;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UrlControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
@DisplayName("testSaveUrl")
void testSaveUrl() {
UrlRequestDto urlRequest = UrlRequestDto.builder()
.url("https://www.naver.com")
.urlTitle("saveUrlTitle")
.urlDescription("saveUrlDescription")
.categoryId(1L)
.build();
ResponseEntity<UrlResponseDto> responseEntity
= restTemplate.postForEntity("/url", urlRequest, UrlResponseDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.CREATED);
UrlResponseDto responseBody = responseEntity.getBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.getUrl()).isEqualTo("https://www.naver.com");
}
@Test
@DisplayName("testGetUrl")
void testGetUrl() {
Url url = new Url(1L, "https://www.naver.com",
"getUrl Title", "getUrl Description",
1L, 1L, null, null);
ResponseEntity<UrlResponseDto> saveEntity
= restTemplate.postForEntity("/url", url, UrlResponseDto.class);
ResponseEntity<UrlResponseDto> responseEntity
= restTemplate.getForEntity("/url/1", UrlResponseDto.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
UrlResponseDto responseBody = responseEntity.getBody();
assertThat(responseBody).isNotNull();
assertThat(responseBody.getUrlId()).isEqualTo(1L);
}
}
> 실행
반응형
'Project_HYEONGARL' 카테고리의 다른 글
Project_07_Spring Security + JWT 토큰에서 추출한 정보 사용하기 (1) | 2024.06.03 |
---|---|
Project_06_SpringSecurity + JWT 인증 후 다른 기능 구현 테스트 코드 작성 (0) | 2024.06.01 |
Project_04_Url 등록 기능 구현 (0) | 2024.05.31 |
Project_03_Spring Security, JWT 구현 (0) | 2024.05.30 |
Project_02_예외 처리하기 @ControllerAdvice, @RestControllerAdvice, @ExceptionHandler (0) | 2024.05.30 |