Kotlin TestCode : Junit5

ashd89ยท2025๋…„ 1์›” 8์ผ

๐Ÿ“Œ Junit5 in Kopring

๐Ÿ“– 1. Annotation

  • @Test : ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ ์ง€์ •
  • @BeforeEach : ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ˆ˜ํ–‰๋˜๊ธฐ ์ „ ์‹คํ–‰
  • @AfterEach : ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ˆ˜ํ–‰๋œ ํ›„ ์‹คํ–‰
  • @BeforeAll : ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์ „ ์ตœ์ดˆ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰
  • @AfterAll : ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•œ ํ›„ ์ตœ์ดˆ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰

=> @BeforeAll๊ณผ @AfterAll์€ ์ „์ฒด์— ์˜ํ–ฅ์„ ์ฃผ๋ฏ€๋กœ
Java์—์„œ๋Š” static์„ค์ • Kotlin์—์„œ๋Š” conpanion object๋กœ ์„ ์–ธ๋œ ๊ณณ์— ์‚ฌ์šฉ (@JvmStatic ํ•„์ˆ˜)

class JunitTest {
	companion object {
        @JvmStatic
        @BeforeAll
        fun beforeAll(): Unit {

        }
    }

    @BeforeEach
    fun beforeEach() {}

    @Test
    fun test1(){

    }

    @Test
    fun test2(){

    }

}

๐Ÿ“– 2. AssertThat : ๋‹จ์–ธ๋ฌธ

  • import์‹œ AssertProvider๋กœ

@Test๊ฐ€ ์ ํžŒ ๋ฉ”์†Œ๋“œ (given / when / then) ์ค‘ then์— ์‚ฌ์šฉํ•˜๋ฉฐ, ์ž˜๋ชป๋œ ๊ฐ’์ด ๋“ค์–ด์™”์„ ๋•Œ, ์˜ˆ์ƒ ๊ฐ’๊ณผ ์‹ค์ œ ๊ฐ’์„ ๋น„๊ต ๊ฐ€๋Šฅ

//then
        assertThat(calculator.number).isEqualTo(7)

  • assertThat(A) A๋Š” ๋Œ€์ƒ ๊ฐ’

assertThrows<์—๋Ÿฌ๋ช…>์œผ๋กœ ์—๋Ÿฌ ๊ฒ€์ถœ ๋ฐ ๋ฉ”์„ธ์ง€ ํ™•์ธ ๊ฐ€๋Šฅ

 val message = assertThrows<IllegalArgumentException> { 
 function1() }.message 
	assertThat(message).isEqualTo("์ž˜๋ชป๋œ ๊ฐ’์ด ๋“ค์–ด์™”์Šต๋‹ˆ๋‹ค")
    
 //context Object ํ™œ์šฉ => ๊ธฐ์–ต์•ˆ๋‚˜๋ฉด Kotlin ๊ธฐ๋ณธ ๋ฌธ๋ฒ•
 assertThrows<IllegalArgumentException> { function1() }.apply {
 	assertThat(message).isEqualTo("์ž˜๋ชป๋œ ๊ฐ’์ด ๋“ค์–ด์™”์Šต๋‹ˆ๋‹ค")
 }

  • isEqualTo(B) B๋Š” ๊ธฐ๋Œ€ ๊ฐ’
    • .isEqualTo
    • .isTrue/ isFalse
    • .hasSize
    • .extracting("name").containsExactlyInAnyOrder("LEE", "Park")
      ๋ฆฌ์ŠคํŠธ ๊ฐ’์˜ name์ด๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์ด ๋งž๋Š”์ง€ (์ˆœ์„œ ์ƒ๊ด€ X)
    • .extracting("name").containsExactly("LEE", "Park")
      ๋ฆฌ์ŠคํŠธ ๊ฐ’์˜ name์ด๋ผ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์ด ๋งž๋Š”์ง€ (์ˆœ์„œ ์ƒ๊ด€ O)

๐Ÿ“– 3. Spring์—์„œ์˜ ๊ฐ ๊ณ„์ธต ํ…Œ์ŠคํŠธ

  • Controller : ์‘๋‹ต๋ฐ›๋Š” JSON ๋ฐ Http ์œ„์ฃผ์˜ ๊ฒ€์ฆ (@SpringBootTest)
  • Domain(์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ๊ฐ์ฒด) : ๊ธฐ์กด์˜ class ํ…Œ์ŠคํŠธ
  • Service, Repository : ์Šคํ”„๋ง ๋นˆ์„ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์œ„์ฃผ์˜ ํ…Œ์ŠคํŠธ (@SpringBootTest)

0) Java Code -> test Kotlin (Java์ฝ”๋“œ ๋ฒ ์ด์Šค๋กœ kotlin ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ)

  • @Autowired๋ฅผ ํ†ตํ•ด Service์™€ Repository๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…
  • ๊ฐ ํ…Œ์ŠคํŠธ์— @DisplayName์„ ํ†ตํ•ด์„œ ์ด๋ฆ„ ์ง€์ • ๊ฐ€๋Šฅ
  • UserCreateRequest("lee", null)๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ƒ์„ฑ์ž ํ•„์ˆ˜
@SpringBootTest
class UserServiceTest @Autowired constructor(
    private val userService: UserService,
    private val userRepository: UserRepository,
    )
{
    @Test
    @DisplayName("์œ ์ € ๋“ฑ๋ก์ด ์ •์ƒ ์ž‘๋™ ํ•œ๋‹ค.")
    fun saveUserTest(){
        //given
        val request = UserCreateRequest("lee", null)

        //when
        userService.saveUser(request)

        //then
        val result = userRepository.findAll()
        assertThat(result).hasSize(1)
        assertThat(result[0].name).isEqualTo("lee")
        assertThat(result[0].age).isNull()
    }

}
  • null์ผ ๊ฒฝ์šฐ kotlin์—์„œ๋Š” null์ด ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธ์ด ์•ˆ๋˜๋ฏ€๋กœ, Java ์—”ํ‹ฐํ‹ฐ์˜ getter์— @Nullable, @NotNull ํ•„์š”
@Entity
public class User {

  @Id
  @GeneratedValue(strategy = IDENTITY)
  private Long id;

  @Column(nullable = false)
  private String name;

  private Integer age;

  @NotNull
  public String getName() {
    return name;
  }

  @Nullable
  public Integer getAge() {
    return age;
  }

์ค‘์š”! ๋™์ผํ•œ ์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ(H2 database)๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฐ์†๋œ ํ…Œ์ŠคํŠธ ๊ณผ์ •์—์„œ ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ์ •์ƒ์ ์ด์–ด๋„ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค

๋”ฐ๋ผ์„œ ๊ฐ ํ…Œ์ŠคํŠธ ํ›„์— AfterEach๋กœ db์ดˆ๊ธฐํ™” ํ•„์š”

@AfterEach
    fun clean() {
        userRepository.deleteAll()
    }

๐Ÿ“– 4. ์ „์ฒด ํ…Œ์ŠคํŠธ ์ง„ํ–‰

Intellij์—์„œ gradle -> verification -> test

0๊ฐœ์˜ ๋Œ“๊ธ€