구독 모델링, API 생성까지 완료하였으니 정상적으로 작동하는지 테스트를 해보아야 한다.
'구독기능'은 User간의 기능이므로, 다수의 User를 만들어주어야 테스트가 가능하다.
때문에 우선 3개의 User를 '회원가입'을 진행시켰다,
1번 유저 ssar
2번 유저 cos
3번 유저 love
DB에서 확인해보자
-> 3명의 user데이터가 DB에 저장이 되어있다
우리가 확인할 데이터는 Subscribe 데이터이다
빠른 테스트를 위해 PostMan으로 진행해보겠다
우선 login부터 해야한다.
login을 하지 않으면 '세션'이 없기 때문에 누가 구독하는지 즉, fromUserId를 찾을 수 없기 때문이다.
-> send를 누르면 간단하게 저 빨간박스안에 HttpStatus상태코드가 200인것을 보고 '로그인'이 되었다는것을 확인할 수 있다
이제 '구독하기'를 진행해보겠다
내가 1번유저인 ssar로 로그인을 진행했으니 2번과 3번유저를 구독해보겠다
-> 1번유저인 내가 2번과 3번유저를 구독했고, 언제 했는지까지 잘 들어와있다.
그렇다면 이제 '중복'으로 구독을 요청하면 어떻게 될까?
-> 바로 HttpStatus상태코드 500번을 내뱉으면서 서버가 터져버린다.
-> VS콘솔을 보면 'Unique 제약조건'을 위배했다는 내용을 확인할 수 있다
이것으로 정상적으로 'Unique 예외처리'도 잘 작동하는것을 확인했다
즉, 테스트는 이것으로 끝이다.
그런데 우리가 터진 서버를 응답해줄수는 없지 않겠는가?
또한 해당오류는 Validation Error가 아니기 때문에 기존에 만들어놓은 CustomException을 못쓴다.
하나 새로 만들어주러 가자
CostomValidationApiException을 복붙하여 CustomApiException 클래스를 만들어준다
package com.cos.photogramstart.handler.ex;
import java.util.Map;
public class CustomApiException extends RuntimeException{
//객체를 구분하기 위해 '시리얼넘버'를 넣어주는것
// JVM을 위해 걸어주는것이다
private static final long serialVersionUID = 1L;
private Map<String, String> errorMap;
public CustomApiException(String message) { //String만 받는 생성자 새로 추가
super(message);
}
public CustomApiException(String message, Map<String, String> errorMap) {
super(message);
this.errorMap =errorMap;
}
public Map<String, String> getErrorMap() {
return errorMap;
}
}
그리고 SubscribeService로 가보자
메서드 내부를 try-catch로 묶어주고, 성공시 원래대로 '구독하기'를 진행하고
실패시 방금 만들어준 CustomApiException을 Throw를 통해 강제로 발동시켜줄것이다.
Exception이 발동한 이류를 message를 통해서 알려주도록 하자
package com.cos.photogramstart.service;
import com.cos.photogramstart.domain.subscribe.SubscribeRepository;
import com.cos.photogramstart.handler.ex.CustomApiException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@RequiredArgsConstructor
@Service
public class SubscribeService {
private final SubscribeRepository subscribeRepository;
@Transactional
public void 구독하기(int fromUserId, int toUserId) {
try {
subscribeRepository.mSubscribe(fromUserId, toUserId);
} catch (Exception e) {
throw new CustomApiException("이미 구독하였습니다.");
}
}
@Transactional
public void 구독취소하기(int fromUserId, int toUserId) { //오류가 날 일이 없다
subscribeRepository.mSubscribe(fromUserId, toUserId);
}
}
-> '구독 취소'하기는 DELETE이기 때문에, 실패해도 에러가 뜨지않고 문제도 발생하지 않기때문에 따로 Exceptionㅇ르 걸어주지는 않았다. 개인적으로 필요해지면 그때 넣어도 늦지 않는다
CustomApiException이 작동할 수 있도록 Handler에서도 받아주자.
맨 밑에 있는 코드를 '복붙'하면 된다
package com.cos.photogramstart.handler;
import com.cos.photogramstart.handler.ex.CustomApiException;
import com.cos.photogramstart.handler.ex.CustomValidationApiException;
import com.cos.photogramstart.handler.ex.CustomValidationException;
import com.cos.photogramstart.util.Script;
import com.cos.photogramstart.web.dto.CMRespDTO;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
@RestController
@ControllerAdvice //모든 Exception을 다 낚아챈다
public class ControllerExceptionHandler {
//JavaScript로 응답하는 Handler
@ExceptionHandler(CustomValidationException.class)
public String validationException(CustomValidationException e) {
//CMRespDto, Script 비교
//1. 클라이언트에게 응답할때는 Script 좋음
//2. Ajax통신을 하거나 Android 통신을 하게되면 CMRespDto가 좋다
//즉, 개발자를 위한 응답에는 CMRespDto, 클라이언트를 위해서는 Script가 좋다
return Script.back(e.getErrorMap().toString());
//자바스크립트로 짜는 부분까지 2가지 방향으로 갔을때 사용자에게 어떤것이 좋을지 판단해보라고 나눈것
}
//CMRespDto 오브젝트를 응답하는 핸들러
@ExceptionHandler(CustomValidationApiException.class)
public ResponseEntity<?> validationApiException(CustomValidationApiException e) {
return new ResponseEntity<>(
new CMRespDTO<>(-1, e.getMessage(), e.getErrorMap()),
HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(CustomApiException.class)
public ResponseEntity<?> apiException(CustomApiException e) {
return new ResponseEntity<>(
new CMRespDTO<>(-1, e.getMessage(),null),
HttpStatus.BAD_REQUEST);
}
// <?>를 사용하면 제네릭 타입이 결정이 된다
// BAD_REQUEST는 400번대 오류이다 -> 너가 요청을 잘못했다
}
'메타코딩 SNS프로젝트' 카테고리의 다른 글
26. 프로필 페이지 - Image를 서버에 업로드하기(UUID활용) (0) | 2022.06.20 |
---|---|
25. 프로필페이지 - Image 모델링하기 (0) | 2022.06.20 |
23. 구독하기 - 구독, 구독취소 API 만들기 (0) | 2022.06.20 |
22. 구독하기 - 모델만들기 (0) | 2022.06.20 |
21. 구독하기 - 연관관계 개념잡기 (0) | 2022.06.20 |