윾진입니다.
단위 테스트.. 막막하지만 해야하니까요.
Spring 기반 웹 서비스에서의 테스트 작성법 같이 공부해요.
단위 테스트
- 단위 테스트 : 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트
- 하나의 모듈 : 각 계층에서 하나의 기능 또는 메소드
- 한 줄 요약 : 하나의 기능이 올바르게 동작하는지 독립적으로 테스트 하는 것
단위 테스트 ? 왜 하는건데 .. 그거..
- 일반적으로 테스트 코드를 작성한다고 하면 거의 단위 테스트를 의미
- 통합 테스트는 실제 여러 컴포넌트들 간의 상호작용을 테스트
- 통합 테스트는 구성 컴포넌트들이 많아질수록 통합 테스트를 위한 시간이 커짐
- 단위 테스트는 독립적으로 테스트 하므로 해당 단위를 유지보수 , 리팩토링 해도 빠르게 문제 파악 가능
단위 테스트 한계
- 단위 테스트는 해당 기능에 대한 독립적인 테스트라서 다른 객체와 데이터 주고 받는 경우 문제 발생
- 문제를 해결하기 우해서는 테스트 기능 . 기능과 연관된 모듈에서의 가짜 데이터 , 정해진 반환값 필요
- 한 줄 요약 : 테스트 하고자 하는 기능과 연관된 다른 모듈은 연결되지 않아야 비로소 독립적인 단위 테스트 가능
단위 테스트 특
- 실제 코드가 변경되면 테스트 코드도 변경 필요
- 테스트 코드라고 대충 ? 다메요. 테스트 코드 역시 가독성있게 , 규칙과 일관되게 작성해야 함
- FIRST 규칙
- 1. FAST : 테스트는 빠르게 동작하고 자주 가동 해야한다.
- 2. Independent : 각각의 테스트는 독립적이어야 하며, 서로에 대한 의존성 없어야 한다.
- 3. Repeatable : 어느 환경에서도 반복이 가능해야 한다.
- 4. Self-Validating : 테스트는 성공 또는 실패 값으로 결과를 내어 자체적으로 검증 되어야 한다.
- 5. Timely : 테스트는 테스트 하려는 실제 코드를 구현하기 직전에 구현 해야 한다.
단위 테스트 코드 작성 공통 준수 사항
JUnit + AssertJ
- JUnit : 자바 단위 테스트를 위한 테스트 프레임워크
- AssertJ : 자바 테스트를 돕기 위해 다양한 문법을 지원하는 라이브러리
- JUnit 만으로 단위 테스트 충분히 작성 가능한데, JUnit에서 제공하는 assertEquals()와 같은 메소드는 AssertJ가 주는 메소드에 비해 가독성이 떨어지므로 JUnit + AssertJ 조합 많이 사용함
- given / when / then 패턴
- Given : 어떤 데이터가 주어질 때 , 준비되었을 때
- When : 어떤 기능 (함수) 을 실행하면
- Then : 어떤 결과가 나와야 한다.
그냥 작성해도 되는데 , 아래처럼 주석으로 단계 명시해주면 더 읽기좋겠죠 ?
우린 intelliJ 사용 중이니 live template 쓰면 더 빠르게 작성 가능하다고 하네요. 테스트 고고링 ~
@Test //해당 메소드가 단위 테스트임을 명시하는 어노테이션
//JUnit 은 테스트 패키지 하위의 @Test 어노테이션이 붙은 메소드를 단위 테스트로 인식해서 실행시킴
@DisplayName("Test") //@DisplayName 어노테이션을 사용해서 읽기 좋은 다른 이름 부여 가능
void test() {
// Given
// When
// Then
}
가짜 객체 지원 프레임워크 써보자
JUnit + Mockito
- Mockito :
개발자가 동작을 직접 제어할 수 있는 가짜 객체를 지원하는 테스트 프레임워크 - 여러 의존성은 단위 테스트를 어렵게 하는데,
이를 해결하기 위해 가짜 객체를 주입시켜주는 Mockito 라이브러리 사용함 - 한 줄 요약 : 가짜 객체에 원하는 결과를 Stub 해서 단위 테스트 진행 가능
[Mockito 사용법]
1. Mock 객체 의존성 주입
가짜 객체 의존성 주입을 위해 크게 3가지 어노테이션 사용됨.
- @Mock : 가짜 객체를 만들어 반환해주는 어노테이션
- @Spy : Stub 하지 않은 메소드들은 원본 메소드 그대로 사용하는 어노테이션
- @InjectMocks : @Mock 또는 @Spy로 생성된 가짜 객체를 자동으로 주입시켜주는 어노테이션
예를 들어 UserController 에 대한 단위 테스트를 작성하고 싶을 때, UserService 를 사용하고 있으면
@Mock 어노테이션을 통해 가짜 UserService 를 만들고 @InjectMocks 를 통해 UserController 에 이를 주입 가능
2. Stub로 결과 처리
의존성이 있는 객체는 가짜 객체를 주입해서 어떤 결과를 반환하라고 정해진 답변을 준비시켜야 함.
Mockito에서는 아래와 같은 Stub 메소드를 제공함.
- doReturn() : 가짜 객체가 특정한 값을 반환해야 하는 경우
- doNothing() : 가짜 객체가 아무 것도 반환하지 않는 경우 (void)
- doThrow() : 가짜 객체가 예외를 발생시키는 경우
자 그럼 이제 진짜 JUnit 으로 단위 테스트하기 위해 환경설정 해주자
Testing in Java & JVM projects
The test process can exit unexpectedly if configured incorrectly. For instance, if the Java executable does not exist or an invalid JVM argument is provided, the test process will fail to start. Similarly, if a test makes programmatic changes to the test p
docs.gradle.org
build.gradle 에서 JUnit5 코드 추가해주자
plugins {
id 'java'
}
group 'org.example'
version '1.0-SNAPSHOT'
repositories {
mavenCentral()
}
test {
useJUnitPlatform()
}
dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.mockito:mockito-junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
'Back-end' 카테고리의 다른 글
[Spring Batch] Spring Batch 구조 및 테스트 (0) | 2024.06.08 |
---|---|
[JPA] JPA에서 On Delete Cascade 제약조건 사용하기 (1) | 2024.06.03 |
[JPA] 최신순으로 목록 조회 (0) | 2024.05.30 |
[Spring Security] 로그인한 사용자의 아이디와 권한(Role) 가져오기 (0) | 2024.05.20 |
[JPA] 양방향 매핑 (0) | 2024.05.13 |