반응형
Review 에서는 학습한 내용을 다시금 기록합니다.
Unit Review는 학습한 내용 중 기존에 알고 있었지만 정확하게 이해하지 못하던 정보와 새롭게 알게된 정보를 기록합니다. 추가적인 설명을 요하는 부분은 댓글로 남겨주세요.
Section Review는 전반적인 Section을 되돌아보고 학습했던 시간과 과정, 내용을 총괄하여 기록합니다.
단위 테스트
* 단위 테스트란?
- 기능 테스트
- 전체 애플리케이션 단위에서, 애플리케이션이 제공하는 기능이 올바르게 동작하는지를 확인하는 테스트를 의미한다.
- 기능 테스트를 진행하기 위해서는 외부 클라이언트와 함께 연관해서 테스트를 진행해야 한다. 따라서 단위 테스트로 부르기는 어렵다.
- 통합 테스트
- 외부 클라이언트와의 연동 없이 내부적인 테스트 코드만으로 애플리케이션의 동작을 확인하는 테스트를 의미한다.
- 통합 테스트 여러 계층이 연관되어 진행되기 때문에 단위 테스트로 부르기는 어렵다.
- 슬라이스 테스트
- 애플리케이션의 특정 계층별로 해당 계층의 동작을 확인하는 테스트를 의미한다.
- 여전히 외부의 데이터를 요구하거나, 내부적으로 DB와 연동하여 테스트하는 등의 과정이 필요하기 때문에 단위 테스트로 부르기는 어렵다.
- 단위 테스트
- 서비스 계층의 핵심 비즈니스 로직을 대상으로 해당 로직의 동작을 확인하는 테스트를 의미한다.
- 하나의 메서드 단위로 테스트가 진행되기 때문에 별도의 외부 API와 연동의 과정이 필요없다.
* 단위 테스트를 위한 F.I.R.S.T 원칙
- First
- 단위 테스트는 빨라야 한다. 테스트가 느리다면 테스트 케이스를 작성하는 의미가 없다.
- Independent
- 단위 테스트는 독립적이어야 한다. 다른 테스트에 종속적이면 안된다.
- A라는 테스트의 결과는 다른 테스트들의 실행과는 관계가 없어야 한다는 말이다.
- Repeatable
- 단위 테스트는 반복 수행이 가능해야 한다.
- 몇 번을 돌려도 같은 결과를 보여야 한다는 말이다.
- Self-validating
- 단위 테스트는 스스로 결과의 옳고 그름을 판단할 수 있어야 한다.
- Timely
- 단위 테스트는 테스트하고자 하는 기능을 구현하기 직전에 작성되어야 한다.
- TDD에 적합한 원칙이지만 지키기 쉽지 않다.
슬라이스 테스트
* API 계층 테스트
- Spring MVC에서는 컨트롤러가 API 계층에 해당한다.
- 즉, API 계층을 테스트한다는 것은 컨트롤러를 테스트하는 것이다.
- 컨트롤러 테스트를 위한 테스트 클래스 구조
- 테스트 클래스에 @SpringBootTest 애너테이션을 붙인다.
- 해당 애너테이션은 Spring Boot 기반의 애플리케이션을 테스트하기 위한 Application Context를 생성한다.
- 테스트 클래스에 @AutoConfigureMockMvc 애너테이션을 붙인다.
- 해당 애너테이션을 통해 테스트에 필요한 애플리케이션의 구성이 자동으로 진행된다.
- 후술할 MockMvc 등의 기능을 이용하기 위해서도 해당 애너테이션이 필요하다.
- MockMvc를 주입받는다.
- MockMvc는 서버를 실행하지 않고도 애플리케이션 내부에서 컨트롤러의 테스트 환경을 지원해주는 일종의 프레임워크다.
* 데이터 액세스 계층 테스트
- 데이터 액세스 계층 테스트를 위한 규칙
- 모든 테스트가 시작되는 시점에서의 DB 상태는 동일해야 한다.
- 테스트는 순서가 보장되지 않는다. 따라서 만일 다른 테스트의 결과로 인한 DB의 변동사항이 초기화되지 않으면, 하나의 테스트의 결과가 다른 테스트에 영향을 미칠 수 있다.
- 데이터 액세스 계층 테스트를 위한 테스트 클래스 구조
- 테스트 클래스에 @DataJpaTest 또는 @DataJdbcTest 애너테이션을 붙인다.
- 해당 애너테이션을 통해 테스트하고자 하는 레포지토리의 기능을 사용하기 위한 Configuration이 진행된다.
- 또한 해당 애너테이션은 @Transactional 애너테이션을 포함하고 있기 때문에, 하나의 테스트 케이스의 실행이 종료되는 시점에 DB에 저장된 데이터가 롤백된다.
- JUnit을 통한 Test가 실행된다면 실행된다면 @Transactional이 적용되어있는 로직은 SELECT를 제외한 모든 쿼리를 Rollback 대상으로 취급한다.
Mockito
* Mockito
- Mockito란?
- 테스트를 위한 Mock 객체를 사용하게 해주는 Mocking Library다.
- 테스트에서 Mock 객체를 사용하는 이유
- 컨트롤러를 테스트한다고 해보자.
- 예를 들어, postMember()를 테스트한다고 하면, 해당 기능의 실질적인 비즈니스 로직을 수행하기 위한 서비스 계층의 메서드를 호출하여 실행한다.
- 해당 메서드는 데이터 액세스 계층의 메서드를 호출하여 실행한다.
- 결국, 컨트롤러를 슬라이스 테스트하려고 했지만, 모든 계층이 연관되어 실행되기 때문에 슬라이스 테스트로 보기 어렵다. 오히려 통합 테스트에 가깝다.
- 그러나 Mock 객체를 사용하면 MemberService 대신 MockMemberService에서 기능을 수행하고 끝낸다. Mock 객체를 사용하지 않을 때보다 연관된 계층의 수가 적어진다. 즉, 테스트가 단순화되어 테스트하고자 하는 대상에만 집중할 수 있다.
- Spring을 사용하여 Mockito 적용
- Mock 객체를 만들어 테스트 클래스에 주입할 클래스 필드에 @MockBean 애너테이션을 붙인다.
- 위의 예시라면, MemberService 필드에 해당 애너테이션을 붙이면 된다.
- Stubbing 메서드인 given() 또는 when()을 사용하여 stub데이터를 생성한다.
- Stubbing은 테스트를 위해 Mock 객체가 항상 동일한 동작을 하도록 지정하는 것을 의미한다.
- 위의 두 메서드는 기능적으로 동일하다.
- 다만 BDD의 관점에서 보았을 때, given - will return 구조가 when - then return의 구조보다 좀 더 읽기 편하다. 테스트 코드도 코드다. 읽기 좋은 테스트를 작성하는 것은 중요하다.
- given()에는 사용하고자 하는 Mock 객체의 메서드를 넣어준다.
- 해당 메서드에 인자가 필요하다면, Mockito.any()에 필요한 인자의 클래스 타입을 넣어 사용한다.
- 마지막으로 willReturn()을 통해 given()에 들어간 메서드가 반환할 Stub 데이터를 지정한다.
given(memberService.createMember(Mockito.any(Member.class)))
.willReturn(member);
- JUnit을 사용하여 Mockito 적용
- 클래스에 @ExtendWith(MockitoExtension.class) 애너테이션을 붙인다.
- Mock 객체로 생성할 필드에 @Mock 애너테이션을 붙인다.
- @Mock 애너테이션이 붙은 Mock 객체를 주입받을 Mock 객체에 @InjectMocks를 붙인다.
- 예를 들어 서비스 계층을 테스트할 때, Service 객체와 Repository객체가 필요하다. 이 때 Service 객체는 Repository객체를 주입받아야한다.
- 이 때, 필드 멤버인 Repository에는 @Mock을 붙여 Mock 객체를 만든다.
- 또 다른 필드 멤버인 Service에는 @InjectMocks를 붙여 Repository를 주입받은 Mock 객체를 만든다.
반응형
'CodeStatesBootCamp > Review' 카테고리의 다른 글
Section 3 - Section Review (2) | 2023.05.09 |
---|---|
Section 3 - Unit 7 : [Spring MVC] API 문서화 Review (0) | 2023.05.03 |
Section 3 - Unit 6 : [Spring MVC] 트랜잭션 Review (0) | 2023.04.26 |
Section 3 - Unit 4 : [Spring MVC] JDBC 기반 데이터 액세스 계층 Review (0) | 2023.04.18 |
Section 3 - Unit 3 : [Spring MVC] 예외 처리 Review (0) | 2023.04.14 |
댓글