Junit5

Junit์€ Java์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŒ… ๋„๊ตฌ์ด๋‹ค.

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ Framework์ค‘ ํ•˜๋‚˜

  • ๋‹จ์ •๋ฌธ์œผ๋กœ Test Case ์ˆ˜ํ–‰๊ฒฐ๊ณผ๋ฅผ ํŒ๋ณ„

  • Annotation์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

JUnit5

Junit5๋Š” ์ด์ „ ๋ฒ„์ „๊ณผ ๋‹ค๋ฅด๊ฒŒ 3๊ฐœ์˜ ์„œ๋ธŒ ํ”„๋กœ์ ํŠธ ๋ชจ๋“ˆ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ๋‹ค.

  • JUnit Platform : TestEngine API, Console Launcher, JUnit 4 based Runner ๋“ฑ ํฌํ•จ

  • JUnit Jupiter : TestEngine API ๊ตฌํ˜„์ฒด๋กœ JUnit 5 ๊ตฌํ˜„

  • JUnit Vintage : TestEngine API ๊ตฌํ˜„์ฒด๋กœ JUnit 3, 4 ๊ตฌํ˜„

    • Junit5์—์„œ JUnit Vintage ๋ชจ๋“ˆ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์–ด JUnit 3,4๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค.

Dependencies

spring boot 2.2.0 ์ดํ›„ ๋ฒ„์ „์—์„œ๋Š” Junit5๊ฐ€ ๊ธฐ๋ณธ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค. Junit5๋Š” Java8 ๋ถ€ํ„ฐ ์ง€์›ํ•˜๋ฉฐ, ์ด์ „ ๋ฒ„์ „์œผ๋กœ ์ž‘์„ฑ๋œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—ฌ๋„ ์ปดํŒŒ์ผ์ด ์ง€์›๋œ๋‹ค.

SpringBoot 2.2.0 ์ด์ „ ๋ฒ„์ „์—์„œ junit5 ์„ค์ •

maven

<!-- spring boot test junit5 ์‚ฌ์šฉ exclusion์„ ํ†ตํ•ด junit4์—์„œ ์ฝ”๋“œ ์‹คํ–‰์‹œ ์‚ฌ์šฉํ•˜๋Š” vintage-engine ์˜ˆ์™ธ์ฒ˜๋ฆฌ-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
  <scope>test</scope>
  <exclusions>
    <exclusion>
      <groupId>org.junit.vintage</groupId>
      <artifactId>junit-vintage-engine</artifactId>
    </exclusion>
  </exclusions>
</dependency>

<!-- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ์— ํ•„์š”ํ•œ junit-jupiter-api ๋ชจ๋“ˆ๊ณผ ํ…Œ์ŠคํŠธ ์‹คํ–‰์„ ์œ„ํ•œ junit-jupiter-engine ๋ชจ๋“ˆ ํฌํ•จ -->
<dependency>
  <groupId>org.junit.jupiter</groupId>
  <artifactId>junit-jupiter-api</artifactId>
</dependency>

gradle

testImplementation ('org.springframework.boot:spring-boot-starter-test') {
	exclude module: 'junit'
}
testImplementation 'org.junit.jupiter:junit-jupiter-api'
testRuntimeOnly'org.junit.jupiter:junit-jupiter-engine'

ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ , ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ƒ์†ํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ง€์›ํ•œ๋‹ค. ๋Œ€๋ถ€๋ถ„ ์–ด๋…ธํ…Œ์ด์…˜์€ junit-jupiter-api๋ชจ๋“ˆ์˜ org.junit.jupiter.api ํŒจํ‚ค์ง€์•ˆ์— ์กด์žฌํ•œ๋‹ค.

์šฉ์–ด

ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค

์ตœ์ƒ์œ„ ํด๋ž˜์Šค, ์Šคํƒœํ‹ฑ ๋ฉค๋ฒ„ ํด๋ž˜์Šค, @Nested ํด๋ž˜์Šค์— ์ ์–ด๋„ ํ•œ๊ฐœ์˜ @Test ์–ด๋…ธํ…Œ์ด์…˜์ด ๋‹ฌ๋ฆฐ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๊ฐ€ ํฌํ•จ๋˜์–ด์žˆ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งํ•œ๋‹ค. ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋Š” abstract์ด๋ฉด ์•ˆ๋˜๊ณ , ํ•˜๋‚˜์˜ ์ƒ์„ฑ์ž๊ฐ€ ์กด์žฌํ•ด์•ผํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ

์•„๋ž˜ ๋ฉ”ํƒ€ ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์—ฌ์ง„ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋Š” ํ…Œ์ŠคํŠธ ํ•  ํด๋ž˜์Šค, ์ƒ์†ํ•œ ๋ถ€๋ชจ ํด๋ž˜์Šค, ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ๋‹ค. abstract๋ฅผ ์„ ์–ธํ•ด์„œ๋Š” ์•ˆ๋˜๋ฉฐ, ์–ด๋– ํ•œ ๊ฐ’๋„ ๋ฐ˜ํ™˜๋˜๋ฉด ์•ˆ๋œ๋‹ค.

  • @Test

  • @RepetedTest

  • @ParameterizedTest

  • @TestFactory

  • @TestTemplate

๋ผ์ดํ”Œ ์‚ฌ์ดํด ๋ฉ”์†Œ๋“œ

์•„๋ž˜ ๋ฉ”ํƒ€ ์–ด๋…ธํ…Œ์ด์…˜์ด ๋ถ™์—ฌ์ง„ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งํ•˜๋ฉฐ, ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋Š” ํ…Œ์ŠคํŠธ ํ•  ํด๋ž˜์Šค, ์ƒ์†ํ•œ ๋ถ€๋ชจ ํด๋ž˜์Šค, ์ธํ„ฐํŽ˜์ด์Šค์— ์„ ์–ธ๋œ๋‹ค. abstract๋ฅผ ์„ ์–ธํ•ด์„œ๋Š” ์•ˆ๋˜๋ฉฐ, ์–ด๋– ํ•œ ๊ฐ’๋„ ๋ฐ˜ํ™˜๋˜๋ฉด ์•ˆ๋œ๋‹ค.

  • @BeforeAll

  • @AfterAll

  • @BeforeEach

  • @AfterEach

Dependency Injection

Junit Jupiter์˜ ์ฃผ๋œ ๋ณ€ํ™”๋กœ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์™€ ๋ฉ”์„œ๋“œ๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ์˜ ์œ ์—ฐํ•จ์ด ์ฆ๊ฐ€ํ•  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ์˜์กด์„ฑ ์ฃผ์ž… ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

ParameterResolver๋Š” ์‹คํ–‰ ์‹œ๊ฐ„ ๋™์•ˆ์— ๋™์ ์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋Š” API๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๋‹ค. ํ˜„์žฌ ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋˜๋Š” 3๊ฐœ์˜ Resolver๊ฐ€ ์žˆ๋‹ค.

ParmeterResolver์„ค๋ช…

TestInfoParameterResolver

TestInfo Resolver์ด๋‹ค. TestInfo ๊ฐ์ฒด๋Š” ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค, ๋ฉ”์„œ๋“œ๋ช…, ๋””์Šคํ”Œ๋ ˆ์ด๋ช…๊ณผ ๊ฐ™์€ ํ˜„์žฌ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

RepetitionInfoParameterResolver

๋ฐ˜๋ณต ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ๋ฉ”์„œ๋“œ(@RepeatedTest ,@BeforeEach ,@AfterEach)์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๋Š” RepetionInfo ๊ฐ์ฒด์— ๋Œ€ํ•œ Resolver์ด๋‹ค.

TestReporterParameterResolver

ํ˜„์žฌ ์‹คํ–‰ํ•˜๋Š” ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋Š” TestReporter ๊ฐ์ฒด์— ๋Œ€ํ•œ Resolver์ด๋‹ค.

TestInfo

๋ฉ”์†Œ๋“œ๋ช…

ํƒ€์ž…

์„ค๋ช…

getDisplayName()

String

@DisplayName ๊ฐ’์ด๋ž‘ ๋™์ผ

getTags()

Set<String>

@Tag ๋ฐฐ์—ด ๊ฐ’

getTestClass()

Optional<Class<?>>

ํŒจํ‚ค์ง€ + ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ช…

getTestMethod()

Optional<Method>

ํŒจํ‚ค์ง€๋ช… + ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ช… + ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ

RepetitionInfo

๋ฉ”์†Œ๋“œ๋ช… / ๋ณ€์ˆ˜๋ช…

ํƒ€์ž…

์„ค๋ช…

getCurrentRepetition()

int

ํ˜„์žฌ ๋ฐ˜๋ณต ํšŸ์ˆ˜

getTotalRepetitions()

int

์ด ๋ฐ˜๋ณต ํšŸ์ˆ˜

DISPLAY_NAME_PLACEHOLDER

String

@DisplayName ๊ฐ’

SHORT_DISPLAY_NAME

String

๋ฐ˜๋ณตํ•  ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” ํ…Œ์ŠคํŠธ๋ช… ๊ธฐ๋ณธ๊ฐ’ : "repetition " + ํ˜„์žฌ ๋ฐ˜๋ณต ํšŸ์ˆ˜ + " of " + ์ด ๋ฐ˜๋ณต ํšŸ์ˆ˜

LONG_DISPLAY_NAME

String

DISPLAY_NAME_PLACEHOLDER + " :: " + SHORT_DISPLAY_NAME

TOTAL_REPETITIONS_PLACEHOLDER

String

ํ˜„์žฌ ๋ฐ˜๋ณต ํšŸ์ˆ˜

CURRENT_REPETITION_PLACEHOLDER

String

์ด ๋ฐ˜๋ณต ํšŸ์ˆ˜

TestInfoParameterResolver

@DisplayName("TestInfo ํ…Œ์ŠคํŠธ")
public class TestInfoTest {

    TestInfoTest(TestInfo testInfo) {
        assertThat("TestInfo ํ…Œ์ŠคํŠธ").isEqualTo(testInfo.getDisplayName());
    }

    @BeforeEach
    void setUp(TestInfo testInfo) {
        String displayName = testInfo.getDisplayName();
        assertThat("demo test").isEqualTo(testInfo.getDisplayName());
    }

    @Test
    @Tag("demo1")
    @DisplayName("demo test")
    void test(TestInfo testInfo) {
        assertThat(testInfo.getTags().contains("demo1")).isTrue();
    }
}

Last updated