hyeonga_code

Project_08_Url 수정/삭제 기능 구현 Controller 테스트 코드 작성 본문

Project_HYEONGARL

Project_08_Url 수정/삭제 기능 구현 Controller 테스트 코드 작성

hyeonga 2024. 6. 3. 06:59
반응형

 

목록 조회의 경우 Pageable을 사용하여 구현할 예정으로 추후 작업할 예정이다.

 

UrlController

 

> 작성  코드

   /**
     * UrlAndCategory 수정
     * @param urlId url ID
     * @param urlRequest 수정할 url 정보
     * @return 수정된 UrlAndCategory 정보
     */
    @PutMapping("/{urlId}")
    public UrlResponseDto updateUrl(@PathVariable Long urlId, @RequestBody UrlRequestDto urlRequest) {
        return UrlResponseDto.fromEntity(urlService.updateUrl(urlId, urlRequest));
    }

    /**
     * UrlAndCategory 삭제
     * @param urlId UrlAndCategory ID
     */
    @DeleteMapping("/{urlId}")
    public void deleteUrl(@PathVariable Long urlId){
        urlService.deleteUrl(urlId);
    }



> 전체 코드

더보기
package com.hyeongarl.controller;

import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.Url;
import com.hyeongarl.service.UrlService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/url")
public class UrlController {
    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));
    }

    /**
     * UrlAndCategory 수정
     * @param urlId url ID
     * @param urlRequest 수정할 url 정보
     * @return 수정된 UrlAndCategory 정보
     */
    @PutMapping("/{urlId}")
    public UrlResponseDto updateUrl(@PathVariable Long urlId, 
    						@RequestBody UrlRequestDto urlRequest) {
        return UrlResponseDto.fromEntity(urlService.updateUrl(urlId, urlRequest));
    }

    /**
     * UrlAndCategory 삭제
     * @param urlId UrlAndCategory ID
     */
    @DeleteMapping("/{urlId}")
    public void deleteUrl(@PathVariable Long urlId){
        urlService.deleteUrl(urlId);
    }

}

 

 

UrlService

> 작성  코드

    /**
     * Url 정보 수정
     * @param urlId 수정할 url Id
     * @param urlRequest 수정한 url 정보
     * @return 수정된 url 정보
     */
    public Url updateUrl(Long urlId, UrlRequestDto urlRequest) {
        Url existUrl = getUrl(urlId);
        Url updateUrl = new Url(
                existUrl.getUrlId(),
                urlRequest.getUrl() != null ? urlRequest.getUrl() : existUrl.getUrl(),
                urlRequest.getUrlTitle() != null ? urlRequest.getUrlTitle() : existUrl.getUrlTitle(),
                urlRequest.getUrlDescription() != null ? urlRequest.getUrlDescription() : existUrl.getUrlDescription(),
                urlRequest.getCategoryId() != null ? urlRequest.getCategoryId() : existUrl.getCategoryId(),
                tokenProvider.userIdFromToken(),
                existUrl.getUrlRegdate(),
                LocalDateTime.now()
        );
        return urlRepository.save(updateUrl);
    }

    /**
     * Url 삭제
     * @param urlId 삭제할 url Id
     */
    public void deleteUrl(Long urlId) {
        urlRepository.deleteById(urlId);
    }


현재 수정 코드에서 Description 기존 값을 모두 지우고 null로 처리하고 싶은 경우는 구현 예정이다.

 

> 전체 코드

더보기
package com.hyeongarl.service;

import com.hyeongarl.config.jwt.TokenProvider;
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 com.hyeongarl.util.UrlValidator;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

@Service
@RequiredArgsConstructor
public class UrlService {
    private final TokenProvider tokenProvider;
    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);
    }

    /**
     * Url 목록 조회
     * @param pageable 조회할 정보
     * @return 조회한 Url 목록
     */
    public Page<Url> getUrls(Pageable pageable) {
        return urlRepository.findAllByUserId(pageable, tokenProvider.userIdFromToken());
    }

    /**
     * Url 정보 수정
     * @param urlId 수정할 url Id
     * @param urlRequest 수정한 url 정보
     * @return 수정된 url 정보
     */
    public Url updateUrl(Long urlId, UrlRequestDto urlRequest) {
        Url existUrl = getUrl(urlId);
        Url updateUrl = new Url(
                existUrl.getUrlId(),
                urlRequest.getUrl() != null ? urlRequest.getUrl() : existUrl.getUrl(),
                urlRequest.getUrlTitle() != null ? urlRequest.getUrlTitle() : existUrl.getUrlTitle(),
                urlRequest.getUrlDescription() != null ? urlRequest.getUrlDescription() : existUrl.getUrlDescription(),
                urlRequest.getCategoryId() != null ? urlRequest.getCategoryId() : existUrl.getCategoryId(),
                tokenProvider.userIdFromToken(),
                existUrl.getUrlRegdate(),
                LocalDateTime.now()
        );
        return urlRepository.save(updateUrl);
    }

    /**
     * Url 삭제
     * @param urlId 삭제할 url Id
     */
    public void deleteUrl(Long urlId) {
        urlRepository.deleteById(urlId);
    }

}

 


UrlRepository

> 작성  코드

    Page<Url> findAllByUserId(Pageable pageable, Long userId);



> 전체 코드

더보기
package com.hyeongarl.repository;

import com.hyeongarl.entity.Url;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface UrlRepository extends JpaRepository<Url, Long> {
    Page<Url> findAllByUserId(Pageable pageable, Long userId);

    @Query("SELECT CASE " +
            "WHEN COUNT(u) > 0 THEN true " +
            "ELSE false END FROM Url u  " +
            "WHERE u.url = :url")
    boolean existsByUrl(String url);
}

 

UrlControllerTest

> 작성  코드

    @Test   // PUT /url/2 수정
    public void testUpdateUrl() {
        ResponseEntity<UrlResponseDto> saveEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, UrlResponseDto.class);

        ResponseEntity<UrlResponseDto> responseEntity
                = restTemplate.exchange("/url/1", HttpMethod.PUT, requestEntity, UrlResponseDto.class);

        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);

        UrlResponseDto responseBody = responseEntity.getBody();
        assertThat(responseBody).isNotNull();
        assertThat(responseBody.getUrl()).isEqualTo("https://www.naver.com");
        assertThat(responseBody.getUrlTitle()).isEqualTo("testUrlTtitle");
        assertThat(responseBody.getUrlDescription()).isEqualTo("testUrlDescription");
    }

    @Test   // DELETE /url/1 삭제 요청
    public void testDeleteUrl() {
        ResponseEntity<UrlResponseDto> saveEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, UrlResponseDto.class);
        ResponseEntity<Void> responseEntity 
                = restTemplate.exchange("/url/1", HttpMethod.DELETE, requestEntity, Void.class);
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
    }



> 전체 코드

더보기
package com.hyeongarl.controller;

import com.hyeongarl.config.jwt.TokenProvider;
import com.hyeongarl.dto.UrlRequestDto;
import com.hyeongarl.dto.UrlResponseDto;
import com.hyeongarl.entity.User;
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.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*;

import java.time.Duration;
import java.time.LocalDateTime;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UrlControllerTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private TokenProvider tokenProvider;

    HttpHeaders headers;
    UrlRequestDto urlRequest;
    HttpEntity<UrlRequestDto> requestEntity;

    @BeforeEach
    void setUp() {
        User testUser = User.builder()
                .userId(1L)
                .userEmail("testUser@email.com")
                .password("testUserPassword")
                .userRegdate(LocalDateTime.now())
                .build();

        String token = tokenProvider.generatedToken(testUser, Duration.ofDays(10));
        headers = new HttpHeaders();
        headers.set("Authorization", "Bearer " + token);

        urlRequest = UrlRequestDto.builder()
                .url("https://www.naver.com")
                .urlTitle("testUrlTtitle")
                .urlDescription("testUrlDescription")
                .categoryId(1L)
                .build();

        requestEntity = new HttpEntity<>(urlRequest, headers);
    }

    @Test
    @DisplayName("testSaveUrl")
    void testSaveUrl() {
        ResponseEntity<UrlResponseDto> responseEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, 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() {
        ResponseEntity<UrlResponseDto> saveEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, UrlResponseDto.class);

        ResponseEntity<UrlResponseDto> responseEntity
                = restTemplate.exchange("/url/1", HttpMethod.GET, requestEntity, UrlResponseDto.class);

        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);

        UrlResponseDto responseBody = responseEntity.getBody();
        assertThat(responseBody).isNotNull();
        assertThat(responseBody.getUrlId()).isEqualTo(1L);
    }

    @Test   // PUT /url/2 수정
    public void testUpdateUrl() {
        ResponseEntity<UrlResponseDto> saveEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, UrlResponseDto.class);

        ResponseEntity<UrlResponseDto> responseEntity
                = restTemplate.exchange("/url/1", HttpMethod.PUT, requestEntity, UrlResponseDto.class);

        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);

        UrlResponseDto responseBody = responseEntity.getBody();
        assertThat(responseBody).isNotNull();
        assertThat(responseBody.getUrl()).isEqualTo("https://www.naver.com");
        assertThat(responseBody.getUrlTitle()).isEqualTo("testUrlTtitle");
        assertThat(responseBody.getUrlDescription()).isEqualTo("testUrlDescription");
    }

    @Test   // DELETE /url/1 삭제 요청
    public void testDeleteUrl() {
        ResponseEntity<UrlResponseDto> saveEntity
                = restTemplate.exchange("/url", HttpMethod.POST, requestEntity, UrlResponseDto.class);
        ResponseEntity<Void> responseEntity
                = restTemplate.exchange("/url/1", HttpMethod.DELETE, requestEntity, Void.class);
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
    }
}

 

 

> 실행

testUpdateUrl()

 

testDeleteUrl()

반응형