hyeonga_code

Project_05_Url 조회 기능 구현 /TestCode 본문

Project_HYEONGARL

Project_05_Url 조회 기능 구현 /TestCode

hyeonga 2024. 6. 1. 05:59
반응형


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);
    }
}

 

> 실행

 

반응형