Test
JUnit5
goodbye
2022. 12. 11. 14:01
Junit 5
- 자바 개발자가 가장 많이 사용하는 테스팅 프레임워크
- 단위 테스트 작성하는 자바 개발자 93% Junit 사용
- 자바 8 이상 필요
- 대체 : TestNG, Spock…
Junit5 Start
- 2.2 + 이상의 버전의 스프링 부트 프로젝트부터 기본으로 JUnit 5 의존성이 추가

- 스프링 부트 프로젝트 사용하지 않는다면
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.5.2</version> <scope>test</scope> </dependency>
- 기본 어노테이션
@Test
@BeforeAll
- 테스트 클래스안에 있는 메서드가 실행되기전에 한번 호출
- static void 로 사용, public 사용불가능
@AfterAll
- 테스트 클래스안에 있는 메서드가 실행 후 한번 호출
- static void 로 사용, public 사용불가능
@BeforeEach
- 테스트 클래스안이 있는 각 메서드가 실행하기전에 한번씩 호출
@AfterEach
- 테스트 클래스안이 있는 각 메서드가 실행하고나서 한번씩 호출
@Disabled
- 해당 메서드의 테스트를 실행하지 않으려고 할때
- 기본 어노테이션 실행 순서 확인

위와 같이 테스트 코드를 작성해보면 다음와 같이 순서대로 실행되는것을 확인할수 있다

- 테스트를 생략하고 싶은 경우
- @Disabled 어노테이션을 붙이면 아래와 같이 테스트가 생략된다


- 테스트에 이름을 표시
@DisplayName
- 어떤 테스트인지 테스트 이름을 보다 쉽게 표현할수 있는 방법을 제공하는 어노테이션
- @DisplayNameGeneration 보다 우선 순위가 높다
@DisplayNameGeneration
(
DisplayNameGenerator
.
ReplaceUnderscores
.
class
)
- method와 class 래퍼런스를 사용해서 테스트 이름을 표기하는 방법 설정
- 기본 구현체로 ReplaceUnderscores 제공
- Run Test
- 단축키 : Ctrl + Shift + R
- 해당 메서드안에서 단축키 입력할경우 : 해당 테스트만 실행
- 중립 영역에서 단축키 입력할 경우 : 해당 클래스 테스트 전체 실행
Juni5 : Assertion
- 실제 값이 기대한 값과 같은지 확인 :
assertEqulas(expected, actual)
- assertEquals(기대값, 실제값, 실패메세지)
- 실패메세지에 문자열 연산이 들어갈경우 테스트 성공, 실패와 관계없이 항상 문자열 연산 실행
- assertEqyals(기대값, 실제값, () → 실패메세지)
- 람다식으로 문자열을 생성하면 테스트가 실패했을때만 문자 연산을 실행한다
- 성능에 유리함
- assertEquals(기대값, 실제값, 실패메세지)
- 값이 null 이 아닌지 확인 :
assertNotNull(actual)
- 다음 조건이 참(true) 인지 확인 :
assertTrue(boolean)
- 모든 확인 구문 확인 :
assertAll(executables…)
- 람다표현식을 이용해서 Excutable Type 으로 묶어서 파라미터로 전달해서 전체 실행
- 중간에 테스트가 실패와 상관없이 모든 테스트 실행 가능
- Unchecked Exception 예와 발생 확인 :
assertThrows(expctedType, executable)
- assertThrows(unChecked Exception Class, () → 예외발생상황 )
- when().thenThrow(Checked Exception.class)
- void 특정_서비스 throws SqlException
- AssertThat import

Junit 5 : 조건에 따라 테스트 실행하기
- /Library/Java/JavaVirtualMachines/jdk-17.0.3.1.jdk/Contents/Home
- 환경변수 등록
- vi ~/.bash_profile
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.3.1.jdk/Contents/Home export PATH=${PATH}:$JAVA_HOME/bin
- source ~/.bash_profile -echo $PATH
assumeTrue(조건)
- @Enabled_ @Disabled_
- EnabledOnOs, DisabledOnOs : OS 환경에 따라 실행여부 결정
- EnabledOnJre, DisabledOnJre
- EnabledIfEnvironmentVariable(named =”환경변수명”, matches=”환경변수값”)
- EnabledOnOs, DisabledOnOs : OS 환경에 따라 실행여부 결정
- Maven 설정
- maven 에서 필터링 하는 방법
- maven test 를 실행해보면 fast 태그가 된 테스트 1건만 실행되는것을 확인 할 수 있다
- Tag Expresstion 참고 URL
Junit5 : Custom Tag
- Junit5 애노테이션을 조합해서 커스텀 태그를 만들 수 있다
- 오타를 줄일수 있고, Type Safe 하다는 장점이 있다

Junit5 : Test 반복하기
- @RepeatedTest
- 반복 횟수와 반복 테스트 이름을 설정 할 수 있다
- {displayName}
- {currentRepetition}
- {totalRepetitions}
- RepetitionInfo 타입의 인자를 받을 수 있다
- 반복 횟수와 반복 테스트 이름을 설정 할 수 있다
- 인자값들의 소스
- @ValueSource
- 인자 값들을 객체에 바인딩해서 해당되는 테스트를 반복실행하려는 경우 에러가 발생한다
- 인자값 타입 변환을 위해 SimpleArgumentConverter 를 상속한 클래스를 구현해주면 해결된다
- 암묵적인 타입 변환 : https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests-argument-conversion-implicit
JUnit 5 User GuideAll Events: Event [type = STARTED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.082280Z, payload = null] Event [type = STARTED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.089339Z, payload = null] Event [type = SKIPPED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:skippedTest()], timestamp = 2018-12-14T12:45:14.094314Z, payload = 'for demonstration purposes'] Event [type = STARTED,https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests-argument-conversion-implicit
- 명시적인 타입 변환
- SimpleArgumenetConverter 상속받은 구현제 제공
- @ConvertWith 사용
- @NullSource, @EmptySource, @NullAndEmptySource : null 문자열, 비어있는 문자열 추가
- @EnumSource
- @MethodSource
- @CsvSource : 여러 인자를 콤마 구분자로 넘길수 있다
- 여러 인자를 각각 전달하는 방법
- 인자값을 조합하는 방법
- ArgumentsAccessor
JUnit 5 User GuideAll Events: Event [type = STARTED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.082280Z, payload = null] Event [type = STARTED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.089339Z, payload = null] Event [type = SKIPPED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:skippedTest()], timestamp = 2018-12-14T12:45:14.094314Z, payload = 'for demonstration purposes'] Event [type = STARTED,https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
-
- Cumtom Accessor
- ArgumentsAggregator 인터페이스 구현
- @AggregateWith
- 제약조건 : 반드시 static inner class 또는 public 메서드여야 한다
- Cumtom Accessor
- @CvsFileSource
- @ArgumentSource
- @ValueSource
Junit5 : Test Instance
- Juit은 테스트 메서드 마다 테스트 인스턴스를 새로 만든다
- 기본전략
- 테스트 메서드를 독립적으로 실행하여 예상치 못한 부작용을 방지하기 위함
- 이 전략을 JUnit5 에서 변경 할 수 잇다
- @TestInstance(Lifecycle.PER_CLASS)
- 테스트 클래스당 인스턴스를 하나만 만들어 사용
- 경우에 따라 테스트 간에 공유하는 모든 상태를 @BeforeEach 또는 @AfterEach 에서 초기화 할 필요
- @BeforeAll 과 @AfterAll
- 인스턴스 메서드 또는 인터페이스에 정의한 default 메서드로 정의 가능
- static keyword 생략 가능해진다
- @TestMethodOrder
- 테스트 메서드들의 순서를 정할수 있다
- MethodOrderer 구현체를 설정
- 기본 구현체
- Alphanumeric
- OrderAnnoation
- Random
JUnit5 : junit-platform.properties
- Junit 설정파일
- src/test/rosources 경로에 넣어두면 적용
- 테스트 인스턴스 라이프 사이클 설정
junit.jupiter.testinstance.lifecycle.default = per_class
- 확장팩 자동 감지 기능
junit.jupiter.extensions.autodetection.enabled = true
- @Disabled 무시하고 실행하기
junit.jupiter.conditions.deactivate = org.junit.*DisabledCondition
- 테스트 이름 표기 전략 설정
junit.jupiter.displayname.generator.default = \
org.junit.jupiter.api.DisplayNameGenerator$ReplaceUnderscores
JUnit5 : 확장모델
- JUnit4 확장모델
- @RunWith(Runner)
- TestRule
- MethodRule
- JUnit5 확장모델
- Extension
- Extenstion 등록 방법
- 선언적인 등록 @ExtendWith
- 프로그래밍 등록 @RegisterExtension
- 자동 등록 자바 ServiceLoader 이용
- 선언적인 등록 @ExtendWith
- 아래와 같이 CustomExtension Class 를 만들고

- 프로그래밍 등록 @RegisterExtension
- CustomExtension 에서 필드의 값을 유동적으로 변경해서 사용하고 싶은 경우
- CustomExtension 에 필드의 값을 주입하는 생성자를 만들고
- Test Class 에 @RegisterExtension 어노테이션을 이용해서 생성자 값 주입
- @ExtendWith 어노테이션에는 생성자를 사용할수없기때문
- 자동 등록 자바 ServiceLoader 이용 방법
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/ServiceLoader.htm
- 확장팩 만드는 방법
- 테스트 실행 조건
- 테스트 인스턴스 팩토리
- 테스트 인스턴스 후-처리기
- 테스트 매개변수 리졸버
- 테스트 라이프사이클 콜백
- 예외 처리
- ...
- Reference URL : https://junit.org/junit5/docs/current/user-guide/#extensions
JUnit 5 User Guide
All Events: Event [type = STARTED, testDescriptor = JupiterEngineDescriptor: [engine:junit-jupiter], timestamp = 2018-12-14T12:45:14.082280Z, payload = null] Event [type = STARTED, testDescriptor = ClassTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase], timestamp = 2018-12-14T12:45:14.089339Z, payload = null] Event [type = SKIPPED, testDescriptor = TestMethodTestDescriptor: [engine:junit-jupiter]/[class:example.ExampleTestCase]/[method:skippedTest()], timestamp = 2018-12-14T12:45:14.094314Z, payload = 'for demonstration purposes'] Event [type = STARTED,


JUnit5 : JUnit4 마이그레이션
- junit-vintage-engine을 의존성으로 추가하면, JUnit 5의 junit-platform으로 JUnit 3과 4로 작성된 테스트를 실행할 수 있다.
- @Rule은 기본적으로 지원하지 않지만, junit-jupiter-migrationsupport 모듈이 제공하는 @EnableRuleMigrationSupport를 사용하면 다음 타입의 Rule을 지원한다.
- ExternalResource
- Verifier
- ExpectedException