Test코드 사용 X (싱글 애플리케이션 (Monolithic Arichitecture)에서의 모습)
- 검증 코드 작성
- 애플리케이션 실행
- PostMan 혹은 브라우저 Request 요청
- log 혹은 print로 결과 검증
- 원하지 않는 결과 발생 시 애플리케이션 종료
- 다시 코드 작성
위와 같은 로테이션이 원하는 결과를 얻을 때까지 돌아가게 됩니다. 간단한 애플리케이션이라도 실행하고 종료하는데 비용이 많이 듭니다. 하지만 Test 코드를 작성한다면 이야기가 달라집니다.
- Test 코드 작성
- Test 코드 실행
- 결과 검증
- Test 코드 수정
애플리케이션을 실행, 종료할 필요가 없습니다. 따라서 비용이 줄어들고, Test 코드를 통해서 명확한 결과 검증이 가능합니다. Test 코드를 작성하지 않았을 때와 비교하면 이점이 명확합니다.
Controller : 클라이언트 요청을 받고 클라이언트에게 결과를 반환 (Presentation Layer)
Service : 비즈니스 로직을 실행하고 결과 반환(Service Layer)
Repository : database에 쿼리를 이용해서 CRUD를 하는 계층(Data Access Layer)
Domain : Entity 클래스
그렇기에 애플리케이션을 실행해서 Test를 진행한다면, 어느 계층에서 잘못된 코드가 있는지 파악하는데 많은 비용이 듭니다. 하지만 Test 코드를 통해서 계층별로 Test를 진행한다면 어느 부분이 잘못된 지 파악을 쉽게 할 수 있습니다.
하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위 테스트 -> 쉽게 말하면 하나의 기능 혹은 메서드라고 이해하면 됩니다.
모듈을 통합화는 과정에서 모듈 간의 호환성을 확인하는 테스트 -> unit이 하나였다면 반대로 여러 개의 계층이 테스트에 참여한 것이라고 생각하면 쉬울 거 같습니다.
단위 테스트 장단점
통합 테스트 장단점
단위 테스트, 통합 테스트 모두 장단점이 명확합니다. 하지만 통합 테스트의 경우 비용을 절감할 수 있는 방법
이 없습니다. 단위 테스트는 단점들을 개선해 나갈 수 있습니다. 그래서 좋은 단위 테스트 작성에 대해서 알아보겠습니다.
좋은 단위 테스트
- 1개의 테스트는 1개의 기능에 대해서만 테스트
- 테스트 주체와 협력자를 구분하기. ( 여기서 주체는 테스트를 할 객체이며, 협력자는 테스트를 진행하기 위해 정의하는 가짜 객체입니다.)
- Given, when, then으로 명확하게 작성하기
Given: 테스트를 진행할 행위를 위한 사전 준비
when: 테스트를 진행할 행위
then: 테스트를 진행한 행위에 대한 결과 검증
@SpringBootTest
통합 테스트 용도로 사용됨
@SpringBootApplication을 찾아가 하위의 모든 Bean을 스캔하여 로드함
그 후 Test용 Application Context를 만들어 Bean을 추가하고, MockBean을 찾아 교체
@ExtendWith
JUnit4에서 @RunWith로 사용되던 어노테이션이 ExtendWith로 변경됨
@ExtendWith는 메인으로 실행될 Class를 지정할 수 있음
@SpringBootTest는 기본적으로 @ExtendWith가 추가되어 있음
@WebMvcTest(Class명.class)
( )안에 작성된 클래스만 실제로 로드하여 테스트를 진행
매게변수를 지정해주지 않으면 @Controller, @RestController, @RestControllerAdvice 등 컨트롤러와 연관된 Bean이 모두 로드됨
스프링의 모든 Bean을 로드하는 @SpringBootTest대신 컨트롤러 관련 코드만 테스트할 경우 사용
@Autowired about Mockbean
Controller의 API를 테스트하는 용도인 MockMvc 객체를 주입 받음
Perform()메소드를 활용하여 컨트롤러의 동작을 확인할 수있음
andExpect(), andDo(), andReturn() 등의 메소드를 같이 활용함
@MockBean
테스트할 클래스에서 주입 받고 있는 객체에 대해 가짜 객체를 생성해주는 어노테이션
해당 객체는 실제 행위를 하지 않음
given() 메소드를 활용하여 가짜 객체의 동작에 대해 정의하여 사용할 수 있음
@AutoConfigureMockMvc
spring.test.mockmvc의 설정을 로드하면서 MockMvc의 의존성을 자동으로 주입
MockMvc 클래스는 REST API 테스트를 할 수 있는 클래스
@Import
필요한 Class들을 Configuration으로 만들어 사용할 수 있음
Configuration Component 클래스도 의존성 설정할 수 있음
Import된 클래스는 주입으로 사용 가능
assertEquals(a, b): a와 b의 값이 동일한지 확인
assertEquals(member.getName(), findMember.getName());
assertSame(a, b): a와 b의 객체가 동일한지 확인
assertNull(a): a가 null인지 확인
assertNotNull(a): a가 null이 아닌지 확인
assertTrue(a): a가 true인지 확인
assertFalse(a): a가 false인지 확인
assertThrows(입셉션 에러 종류 a, 발생하는 로직 b) : b 로직시에 a 입셉션이 발생하는지 확인
코드
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));//예외가 발생해야 한다.
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
assertThat : AssertJ 라이브러리에 포함된 메서드, 어떤 조건이 참인지 확인
import static org.assertj.core.api.Assertions.*;
코드
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));//예외가 발생해야 한다. assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");