๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ“– Java&Spring

Intellij) JUnit5 ์„ค์ •ํ•  ์‚ฌ๋žŒ ๊ดŒ

์š”์ฆ˜ ์ผํ•˜๋ฉด์„œ ๋‚ด๊ฐ€ ์ œ์ผ ์‹ ๊ฒฝ ์“ฐ๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ž˜ ๋‚จ๊ธฐ๋Š” ๊ฒƒ์ด๋‹ค

๋ชจ๋“  ์ผ์€ ๋ˆ„๊ตฌ๋‚˜ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์ง€๋งŒ

์ฝ”๋“œ๋งˆ๋‹ค ์žˆ๋Š” ์‚ฌ์—ฐ์€... ๊ทธ ์‚ฌ๋žŒ๋ฐ–์— ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค ๐Ÿฅน

์™œ ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜๊ฒŒ ๋๋ƒ๊ตฌ์š”? ์ €๋„ ๊ทธ๋Ÿฌ๊ณ  ์‹ถ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค

 

๊ทธ๋ž˜์„œ!!

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์—ฌ๋Š๋•Œ์™€ ๋‹ค๋ฆ„์—†์ด ์ž‘์„ฑํ•˜๋˜ ์ค‘...

๊ธฐ์กด์—๋Š” JUnit4 ๋ฒ„์ „์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ

๋‹ค๋ฅธ ๋‹ด๋‹น์ž๊ฐ€ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์‹คํ–‰ ์‹œ ๋น ๋ฅด๊ฒŒ ๋‚ด์šฉ์„ ํŒŒ์•…ํ•˜์‹œ๋ฉด ์ข‹๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค

 

๋ถˆ-ํŽธ

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋จผ์ € ๋งํ•˜์ž๋ฉด..

 

ํŽธ-์•ˆ

 

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ์•„ ์ด๋Ÿฐ ํ…Œ์ŠคํŠธ~๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•˜๊ธธ ์›ํ–ˆ๋‹ค

 

๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•ด์„œ๋Š” @DisplayName ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ์ด ํ•„์š”ํ–ˆ๊ณ ,

์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” JUnit ๋ฒ„์ „์„ ์—…๊ทธ๋ ˆ์ด๋“œ ํ•ด์•ผํ–ˆ๋‹ค

 


1. JUnit5 ์˜์กด์„ฑ ์ถ”๊ฐ€

(1) build.gradle

dependencies {
    // JUnit 5 ์˜์กด์„ฑ
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    
    // Mockito ์˜์กด์„ฑ
    testImplementation('org.mockito:mockito-core:3.12.4')
}
//...
test{
    useJUnitPlatform()
}

 

(2) pom.xml

		<!-- JUnit 5 ์˜์กด์„ฑ -->
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-api</artifactId>
			<version>5.8.1</version> <!-- ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ๋Œ€์ฒดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -->
			<scope>test</scope>
		</dependency>

		<!-- Mockito ์˜์กด์„ฑ -->
		<dependency>
			<groupId>org.mockito</groupId>
			<artifactId>mockito-core</artifactId>
			<version>3.12.4</version> <!-- ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ๋Œ€์ฒดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -->
			<scope>test</scope>
		</dependency>

 

2. JUnit4 vs JUnit5

 

https://junit.org/junit5/docs/current/user-guide/

 

JUnit 5 User Guide

Although the JUnit Jupiter programming model and extension model do not support JUnit 4 features such as Rules and Runners natively, it is not expected that source code maintainers will need to update all of their existing tests, test extensions, and custo

junit.org

๊ณต์‹ ๋ฌธ์„œ๊ฐ€ ์ •๋ฆฌ๊ฐ€ ์ž˜ ๋˜์–ด์žˆ์–ด์„œ ์š”๋…€์„์„ ์ธ์šฉํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค

 

๋‘˜์˜ ์ฐจ์ด์ ์€ ํฌ๊ฒŒ ์•„๋ž˜๋กœ ์ •๋ฆฌํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค

 

Java ๋ฒ„์ „์„ ๋ช‡ ๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š”์ง€?

๊ตฌ์กฐ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋‹ฌ๋ผ์กŒ๋Š”์ง€?

์‚ฌ์šฉ๋ฒ•์ด ์–ด๋–ป๊ฒŒ ๋‹ฌ๋ผ์กŒ๋Š”์ง€?

 

(1) Java ๋ฒ„์ „

 

Java 8 ๋˜๋Š” ๊ทธ ์ด์ƒ์„ ์จ์•ผํ•œ๋‹ค๊ณ  ๋˜์–ด์žˆ๋Š”๋ฐ์š”, ํ…Œ์ŠคํŠธํ•˜๋Š”๋ฐ๋Š” ์ด์ „ ๋ฒ„์ „์ด์–ด๋„ ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค

 

JUnit 5 requires Java 8 (or higher) at runtime. However, you can still test code that has been compiled with previous versions of the JDK.
๐ŸงšJUnit 5๋Š” ๋Ÿฐํƒ€์ž„ ์‹œ Java 8(๋˜๋Š” ๊ทธ ์ด์ƒ)์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์ „ ๋ฒ„์ „์˜ JDK๋กœ ์ปดํŒŒ์ผ๋œ ์ฝ”๋“œ๋ฅผ ๊ณ„์† ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

(2) ๊ตฌ์ฐจํ•œ..๊ตฌ์กฐ ์ฐจ์ด

JUnit4๋Š” ์˜ฌ์ธ์› ํ† ๋„ˆ ๊ฐ™์€ ๋…€์„์ž…๋‹ˆ๋‹ค.

๊ทผ๋ฐ JUnit5๋Š” ํ”Œ๋žซํผ์˜ ๊ตฌ์„ฑ์ด ์ถ”๊ฐ€ ๋์Šต๋‹ˆ๋‹ค

 

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

 

JUnit Platform

JVM์—์„œ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ ์‹คํ–‰ํ•˜๋Š” ๊ธฐ๋ณธ์ด ๋˜๋Š” ๋…€์„์ž…๋‹ˆ๋‹ค

TestEngine API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค๋‹ˆ๋‹ค

Console Lancher๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ๋„ ์ด ๋…€์„์ž…๋‹ˆ๋‹ค

IntelliJ ๊ฐ™์€ IDE์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

 

JUnit Jupiter ๐Ÿช

(์™œ ๋ชฉ์„ฑ ์ด๋ชจ์ง€๋Š” ์—†์ฃ )

์ด ๋…€์„์€ ํ™•์žฅํŒฉ ๊ฐ™์€ ์นœ๊ตฌ์ž…๋‹ˆ๋‹ค

JUnit 5์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ํ™•์žฅ์„ ํ•˜๊ธฐ ์œ„ํ•œ

์ƒˆ๋กœ์šด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ชจ๋ธ๊ณผ ํ™•์žฅ ๋ชจ๋ธ์˜ ์ข…ํ•ฉ ์„ธํŠธ์ž…๋‹ˆ๋‹ค

 

JUnit Vintage

JUnit3๊ณผ JUnit4 ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ TestEngine์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค

๊ฐœ์ธ์ ์œผ๋กœ ์ด๋ฆ„ ๋˜๊ฒŒ ์ž˜ ์ง€์—ˆ๋‹ค ์ƒ๊ฐํ•จ

 

 

(3) Annotation ์‚ฌ์šฉ

JUnit 4 JUnit 5 ์„ค๋ช…
@Test @Test ๋‚˜๋Š”์•ผ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ
N/A @ParameterizedTest ๋งค๊ฐœ ๋ณ€์ˆ˜ํ™”๋œ ํ…Œ์ŠคํŠธ
N/A @RepeatedTest ๋ฐ˜๋ณต ํ…Œ์ŠคํŠธ ์‹œ ์‚ฌ์šฉ
N/A @TestFactory ๋™์  ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ํŒฉํ† ๋ฆฌ
N/A @TestTemplate ์ปจํ…์ŠคํŠธ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์—ฌ๋Ÿฌ ๋ฒˆ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Œ
N/A @TestClassOrder ํ…Œ์ŠคํŠธํ•  ํด๋ž˜์Šค ์ˆœ์„œ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค
@FixMethodOrder @TestMethodOrder ๋ฉ”์„œ๋“œ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค
N/A @TestInstance ํ…Œ์ŠคํŠธ ์ธ์Šคํ„ด์Šค ์ˆ˜๋ช… ์ฃผ๊ธฐ๋ฅผ ์„ค์ •
N/A @DisplayName ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋‚˜ ๋ฉ”์„œ๋“œ ๋ณด์—ฌ์งˆ ์ด๋ฆ„ ์ง€์ •
N/A @DisplayNameGeneration ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ๋ณด์—ฌ์งˆ ์ด๋ฆ„ ์ง€์ •
@BeforeClass @BeforeAll ํ˜„์žฌ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰
@AfterClass @AfterAll ํ˜„์žฌ ํด๋ž˜์Šค์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์‹คํ–‰ ํ›„ ์‹คํ–‰
@Before @BeforeEach ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ์ „์— ์‹คํ–‰
@After @AfterEach ๊ฐ ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ ํ›„์— ์‹คํ–‰
@Ignore @Disabled ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ/ํด๋ž˜์Šค ๋น„ํ™œ์„ฑํ™” ํ•  ์ˆ˜ ์žˆ์ธฐ
N/A @TestFactory ๋™์  ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ํŒฉํ† ๋ฆฌ
N/A @Nested ์ค‘์ฒฉ ํ…Œ์ŠคํŠธ
@Category @Tag ํƒœ๊น…(Tagging) ๋ฐ ํ•„ํ„ฐ๋ง(Filtering)
N/A @ExtendWith ์‚ฌ์šฉ์ž ์ •์˜ ํ™•์žฅ ๋“ฑ๋ก
N/A @Timeout ์‹คํ–‰ ์ง€์ • ๊ธฐ๊ฐ„์„ ์ดˆ๊ณผํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Œ
N/A @RegisterExtension ํ™•์žฅ ๋“ฑ๋ก
N/A @TempDir ์ž„์‹œ ๋””๋ ‰ํ„ฐ๋ฆฌ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์‚ฌ์šฉ

 

 

3. ์‚ฌ์šฉ ์˜ˆ์ œ

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("A special test case")
class DisplayNameDemo {

    @Test
    @DisplayName("Custom test name containing spaces")
    void testWithDisplayNameContainingSpaces() {
    }

    @Test
    @DisplayName("โ•ฏ°โ–ก°๏ผ‰โ•ฏ")
    void testWithDisplayNameContainingSpecialCharacters() {
    }

    @Test
    @DisplayName("๐Ÿ˜ฑ")
    void testWithDisplayNameContainingEmoji() {
    }

}

 

์ด๋ชจ์ง€๋„ ์‚ฌ์šฉํ•˜๋Š” ์ด ๋…€์„ ์ œ๋ฒ• ๊ท€์—ฝ์Šต๋‹ˆ๋‹ค

๋‚˜๋จธ์ง€ ์–ด๋…ธํ…Œ์ด์…˜๋„ JUnit ์˜ˆ์ œ๊ฐ€ ์•„์ฃผ ์ž˜ ๋‚˜์™€์žˆ๋‹ค์š”