✔ 테스트
이 포스팅은 토비의 스프링을 읽고 개인적으로 정리하는 글입니다.
스프링이 개발자에게 제공하는 가장 중요한 가치
- 객체지향과 테스트라고 생각한다.
- 테스트는 만들어진 코드를 확신할 수 있게 해주고, 변화에 유연하게 대처할 수 있는 자신감을 준다.
- 테스트는 스프링을 학습하는 데 있어 가장 효과적인 방법의 하나
테스트의 유용성
- 테스트란 결국 내가 예상하고 의도했던 대로 코드가 정확히 동작하는지를 확인해서, 만든 코드를 확신할 수 있게 해주는 작업
- 테스트의 결과가 원하는 대로 나오지 않는 경우에는 코드나 설계에 결함이 있음을 알 수 있다
- 디버깅을 거쳐 결국 최종적으로 테스트가 성공하면 모든 결함이 제거됐다는 확신을 얻을 수 있음
작은 단위의 테스트
- 테스트하고자 하는 대상이 명확하다면 그 대상에만 집중해서 테스트하는 것이 바람직
- 테스트는 가능하면 작은 단위로 쪼개서 집중해서 할 수 있어야 한다
- 관심사의 분리라는 원칙이 여기에도 적용된다
- 작은 단위의 코드에 대해 테스트를 수행한 것을 단위 테스트라고 한다
자동수행 테스트 코드
- 테스트는 자동으로 수행되도록 코드로 만들어지는 것이 중요하다.
- 애플리케이션을 구성하는 클래스 안에 테스트 코드를 포함시키는 것보다는 별도로 테스트용 클래스를 만들어서 테스트 코드를 넣는 편이 낫다.
- 자동으로 수행되는 테스트의 장점은 자주 반복할 수 있다는 점이다.
개발자를 위한 테스팅 프레임워크 JUnit
- 스프링의 핵심 기능 중 하나인 스프링 테스트 모듈도 JUnit을 이용한다.
테스트 주도 개발(TDD)
- 만들고자 하는 기능의 내용을 담고 있으면서 만들어진 코드를 검증도 해줄 수 있도록 테스트 코드를 먼저 만들고 테스트를 성공하게 해주는 코드를 작성하는 방식의 개발 방법을 테스트 주도 개발이라고 한다.
- TDD의 기본원칙은
실패한 테스트를 성공시키기 위한 목적이 아닌 코드는 만들지 않는다
이다.
- TDD에서는 테스트 작성하고 이를 성공시키는 코드를 만드는 작업의 주기를 가능한 한 짧게 가져가도록 권장한다.
- TDD를 하면 자연스럽게 단위 테스트를 만들 수 있다.
- 테스트는 코드를 작성한 후에 가능한 빨리 실행할 수 있어야 한다. 테스트 없이 한 번에 너무 많은 코드를 만드는 것은 좋지 않다.
테스트 코드 개선
@BeforeEach
를 활용해 중복 코드를 제거하자!
- 모든 테스트 메소드에서 사용하는 것이 아닌 일부에서만 사용하는 코드가 있다면
@BeforeEach
대신에 일반 메소드 추출 방식을 사용해 처리한다.
테스트를 위한 애플리케이션 컨텍스트 관리
- 테스트 메소드의 컨텍스트 공유
- 스프링의 JUnit 확장 기능은 테스트가 실행되기 전에 딱 한 번만 애플리케이션 컨텍스트를 만들어두고, 테스트 오브젝트가 만들어질때마다 특별한 방법을 이용해 애플리케이션 컨텍스트 자신을 테스트 오브젝트의 특정 필드에 주입해주는 것이다.
- 테스트의 수행시간은 갈수록 빨라지는데 이는 최초에 컨텍스트를 생성하는 시간이 필요하기 때문이다.
- 같은 설정파일을 가진 애플리케이션 컨텍스트를 각기 다른 테스트 클래스가 사용한다면 단 한 개의 애플리케이션 컨텍스트만 만든다.
@Autowired
- 스프링의 DI에 사용되는 특별한 애노테이션
@Autowired
가 붙은 인스턴스 변수가 있으면, 테스트 컨텍스트 프레임워크는 변수 타입과 일치하는 컨텍스트 내의 빈을 찾는다. 일치하는 빈을 찾으면 주입해준다.
- 스프링 애플리케이션 컨텍스트는 초기화할 때 자기 자신도 빈으로 등록한다.
- 같은 타입의 빈이 두 개 이상 있는 경우에는 타입만으로는 어떤 빈을 가져올지 결정할 수 없다.
- 먼저 변수의 이름과 같은 이름의 빈이 있는지 확인
- 변수 이름으로도 빈을 찾을 수 없는 경우에는 예외가 발생함
테스트를 위한 별도의 DI 설정
- 아예 테스트에서 사용될 DataSource 클래스가 빈으로 정의된 테스트 전용 설정파일을 따로 만들어두는 방법
컨테이너 없는 DI 테스트
@BeforeEach
에서 직접 오브젝트를 생성하고 DI 해준다
- 하지만 JUnit이 매번 새로운 테스트 오브젝트를 만드는 단점이 생긴다.
침투적 기술과 비침투적 기술
- 침투적 기술
- 기술을 적용했을 때 애플리케이션 코드에 기술 관련 API가 등장하거나 특정 인터페이스나 클래스를 사용하도록 강제하는 기술
- 애플리케이션 코드가 해당 기술에 종속되는 결과를 가져온다
- 비침투적 기술
- 애플리케이션 로직을 담은 코드에 아무런 영향을 주지 않고 적용이 가능
- 기술에 종속적이지 않은 순수한 코드를 유지할 수 있게 해준다
- 스프링은 이런 비침투적인 기술의 대표적인 예
DI를 이용한 테스트 방법 선택
- 항상 스프링 컨테이너 없이 테스트할 수 있는 방법을 우선적으로 고려(속도가 빠름)
- 여러 오브젝트와 복잡한 의존관계를 갖고 있는 오브젝트를 테스트해야 할 경우가 있을 땐 스프링의 설정을 이용한 DI 방식의 테스트를 이용하면 편리
학습 테스트의 장점
- 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다.
- 학습 테스트 코드를 개발 중에 참고할 수 있다.
- 프레임워크나 제품을 업그레이드할 때 호환성 검증을 도와준다.
- 테스트 작성에 대한 좋은 훈련이 된다.
- 새로운 기술을 공부하는 과정이 즐거워진다.
스프링을 사용하는 개발자라면 자신이 만든 코드를 테스트로 검증하는 방법을 알고 있어야 하며, 테스트를 개발에 적극적으로 활용할 수 있어야 한다.