체크 예외 예제를 만들어보자.
@Test 어노테이션이 아래와 같이 나와야 하는데
import org.junit.jupiter.api.Test;
내가 지정한 어노테이션은 아래와 같다. 그래도 빌드는 잘된다.
import org.testng.annotations.Test;
package hello.jdbc.exception.basic;
import lombok.extern.slf4j.Slf4j;
import org.testng.annotations.Test;
@Slf4j
public class CheckedTest {
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
}
/**
* Exception을 상속받은 예외는 체크 예외가 된다.
*/
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
/**
* Checked 예외는
* 예외를 잡아서 처리하거나, 던지거나 둘중 하나를 필수로 선택해야 한다.
*
*/
static class Service {
Repository repository = new Repository();
/**
* 예외를 잡아서 처리하는 코드
*/
public void callCatch() {
try {
repository.call();
} catch (MyCheckedException e) {
// 예외 처리 로직
log.info("예외 처리, message={}", e.getMessage(), e);
}
}
}
static class Repository {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
}
보류...
@Test 어노테이션이랑 Assertions 부분이 import가 안된다 해결중..
package hello.jdbc.exception.basic;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CheckedTest {
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
}
@Test
void checked_throw() {
Service service = new Service();
Assertions.assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
/**
* Exception을 상속받은 예외는 체크 예외가 된다.
*/
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
/**
* Checked 예외는
* 예외를 잡아서 처리하거나, 던지거나 둘중 하나를 필수로 선택해야 한다.
*
*/
static class Service {
Repository repository = new Repository();
/**
* 예외를 잡아서 처리하는 코드
*/
public void callCatch() {
try {
repository.call();
} catch (MyCheckedException e) {
// 예외 처리 로직
log.info("예외 처리, message={}", e.getMessage(), e);
}
}
/**
* 체크 예외를 밖으로 던지는 코드
* 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야한다.
* @throws MyCheckedException
*/
public void callThrow() throws MyCheckedException {
repository.call();
}
}
static class Repository {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
}
Intellij에서 import 하는 기능이 몇 개 막혔다. Can not resolve라고 뜨게 된다.
참고 사이트를 보고 해결중인데 잘 되지 않는다.
IntelliJ cannot resolve symbol.. 에러 해결
문제 IntelliJ IDEA를 쓰고 있으며, 멀쩡히 잘 쓰다가 종종 잊을만하면 Cannot resolve symbol.. 에러가 나온다. 예를 들면 아래와 같이 import가 제대로 안되는 것이다.
hyesun03.github.io
assertThat 계속 빨간불로만 떠있습니다. 인폴트도 어떤것도 되지 않습니다. - 인프런 | 질문 & 답변
Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername());Asse...
www.inflearn.com
스프링 Cannot resolve symbol 'assertThat' 에러
스프링을 학습하던 도중에 Cannot resolve symbol 'assertThat'라는 에러와 만나게됐다. 본래라면 에러가 아니라고 할 수도 있겠다 인텔리제이의 강력한 Import기능을 너무 신뢰했기 때문에 에러를 찾는
www.goodsource.co.kr
Cannot resolve symbol 'Assert' assertThat 에러 해결하기
1. 기대한 바 TDD (Test Driven Development : 테스트 주도 개발)을 하기 위해 Test코드를 작성하였습니다. Test코드를 작성 중 입력값의 검증 또는 예외상황을 디버깅하기 위한 용도로 assertThat를 사용하려
aonee.tistory.com
Cannot resolve symbol 'Test'
Cannot resolve symbol 'Assertions'
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
}
@Test
void checked_throw() {
Service service = new Service();
assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
Exception을 상속받은 예외는 체크 예외가 된다.
static class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
- MyCheckedException 는 Exception 을 상속받았다. Exception 을 상속받으면 체크 예외가 된다.
- 참고로 RuntimeException 을 상속받으면 언체크 예외가 된다. 이런 규칙은 자바 언어에서 문법으로 정한
것이다.
- 예외가 제공하는 여러가지 기본 기능이 있는데, 그 중에 오류 메시지를 보관하는 기능도 있다. 예제에서 보는
것 처럼 생성자를 통해서 해당 기능을 그대로 사용하면 편리하다.
아래는 예외를 잡아서 처리하는 코드이다.
@Test
void checked_catch() {
Service service = new Service();
service.callCatch();
}
- service.callCatch() 에서 예외를 처리했기 때문에 테스트 메서드까지 예외가 올라오지 않는다.
실행 순서를 분석해보면
- test service.callCatch() repository.call() [예외 발생, 던짐]
- test service.callCatch() [예외 처리] repository.call()
- test [정상 흐름] service.callCatch() repository.call()
Repository.call() 에서 MyUncheckedException 예외가 발생하고, 그 예외를 Service.callCatch() 에서 잡는 것을 확인이 가능하다.
log.info("예외 처리, message={}", e.getMessage(), e);
실행 결과
[Test worker] INFO hello.jdbc.exception.basic.CheckedTest - 예외 처리, message=ex
hello.jdbc.exception.basic.CheckedTest$MyCheckedException: ex
at
hello.jdbc.exception.basic.CheckedTest$Repository.call(CheckedTest.java:64)
at
hello.jdbc.exception.basic.CheckedTest$Service.callCatch(CheckedTest.java:45)
at hello.jdbc.exception.basic.CheckedTest.checked_catch(CheckedTest.java:14)
- 실행 결과 로그를 보면 첫줄은 우리가 남긴 로그가 그대로 남는 것을 확인할 수 있다.
- 그런데 두 번째 줄 부터 예외에 대한 스택 트레이스가 추가로 출력된다.
- 이 부분은 로그를 남길 때 로그의 마지막 인수에 예외 객체를 전달해주면 로그가 해당 예외의 스택
트레이스를 추가로 출력해주는 것이다.
- log.info("예외 처리, message={}", e.getMessage(), e); 여기서 마지막에 있는 e
부분이다.
체크 예외를 잡아서 처리하는 코드
try {
repository.call();
} catch (Exception e) {
//예외 처리 로직
}
- 체크 예외를 잡아서 처리하려면 catch(..) 를 사용해서 예외를 잡으면 된다.
- 여기서는 MyCheckedException 예외를 잡아서 처리한다.
catch는 해당 타입과 그 하위 타입을 모두 잡을 수 있다.
public void callCatch() {
try {
repository.call();
} catch (Exception e) {
//예외 처리 로직
}
}
- catch 에 MyCheckedException 의 상위 타입인 Exception 을 적어주어도 MyCheckedException 을
잡을 수 있다.
- catch 에 예외를 지정하면 해당 예외와 그 하위 타입 예외를 모두 잡아준다.
- 물론 정확하게 MyCheckedException 만 잡고 싶다면 catch 에 MyCheckedException 을 적어주어야
한다.
예외를 처리하지 않고, 밖으로 던지는 코드를 보자.
@Test
void checked_throw() {
Service service = new Service();
assertThatThrownBy(() -> service.callThrow())
.isInstanceOf(MyCheckedException.class);
}
- service.callThrow() 에서 예외를 처리하지 않고, 밖으로 던졌기 때문에 예외가 테스트 메서드까지
올라온다.
- 테스트에서는 기대한 것 처럼 MyCheckedException 예외가 던져지면 성공으로 처리한다.
실행 순서 분석
- 1. test service.callThrow() repository.call() [예외 발생, 던짐]
- 2. test service.callThrow() [예외 던짐] repository.call()
- 3. test [예외 도착] service.callThrow() repository.call()
체크 예외를 밖으로 던지는 코드
public void callThrow() throws MyCheckedException {
repository.call();
}
- 체크 예외를 처리할 수 없을 때는 method() throws 예외 을 사용해서 밖으로 던질 예외를 필수로
지정해주어야 한다. 여기서는 MyCheckedException 을 밖으로 던지도록 지정해주었다.
체크 예외를 밖으로 던지지 않으면 컴파일 오류 발생
public void callThrow() {
repository.call();
}
- throws를 지정하지 않으면 컴파일 오류가 발생한다.
- Unhandled exception: hello.jdbc.exception.basic.CheckedTest.MyCheckedException
- 체크 예외의 경우 예외를 잡아서 처리하거나 또는 throws 를 지정해서 예외를 밖으로 던진다는 선언을
필수로 해주어야 한다.
체크 예외를 밖으로 던지는 경우에 해당 타입과 그 하위 타입을 모두 던질 수 있음.
public void callThrow() throws Exception {
repository.call();
}
- throws 에 MyCheckedException 의 상위 타입인 Exception 을 적어주어도 MyCheckedException 을
던질 수 있다.
- throws 에 지정한 타입과 그 하위 타입 예외를 밖으로 던진다.
- 물론 정확하게 MyCheckedException 만 밖으로 던지고 싶다면 throws 에 MyCheckedException 을
적어주어야 한다.
체크 예외의 장단점
- 체크 예외는 예외를 잡아서 처리할 수 없을 때, 예외를 밖으로 던지는 throws 예외를 필수로 선언해야
한다. 그렇지 않으면 컴파일 오류가 발생한다. 이것 때문에 장점과 단점이 동시에 존재
- 장점: 개발자가 실수로 예외를 누락하지 않도록 컴파일러를 통해 문제를 잡아주는 훌륭한 안전 장치
- 단점: 하지만 실제로는 개발자가 모든 체크 예외를 반드시 잡거나 던지도록 처리해야 하기 때문에, 너무
번거로운 일이 됨. 크게 신경쓰고 싶지 않은 예외까지 모두 챙겨야 함
<출처 김영한:스프링 DB 1편 - 데이터 접근 핵심 원리>
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1/dashboard
스프링 DB 1편 - 데이터 접근 핵심 원리 - 인프런 | 강의
백엔드 개발에 필요한 DB 데이터 접근 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의
www.inflearn.com
'Spring > SpringDB' 카테고리의 다른 글
체크 예외 활용 (0) | 2022.06.22 |
---|---|
언체크 예외 기본 이해 (0) | 2022.06.22 |
자바 예외 계층 & 예외 기본 규칙 (0) | 2022.06.20 |
트랜잭션 AOP 정리 & 스프링 부트의 자동 리소스 등록 (0) | 2022.06.20 |
트랜잭션 AOP 적용 (0) | 2022.06.20 |