๐Ÿณ์ฝ”ํ”„๋ง์— ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ๋„์ž…ํ•˜๋‹ค.

๊น€์ข…์™„ยท2022๋…„ 9์›” 23์ผ
0

์ด๋ฒˆ์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์— ์ค‘์š”์„ฑ์— ๋Œ€ํ•ด ์ธ์ง€ํ•˜๊ฒŒ ๋˜์–ด์„œ ํšŒ์‚ฌ ํ”„๋กœ์ ํŠธ์— ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ๋„์ž…ํ•ด๋ณด์•˜๋‹ค. Junit5๋ฅผ ์‚ฌ์šฉํ•˜์˜€๊ณ  ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๋ณด๋‹ค๋Š” ์šฐ์„  ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ๋จผ์ € ๊ตฌํ˜„ํ•˜์—ฌ ๋ณด์•˜๋‹ค. ํ•ด๋‹น ๊ธ€์—์„œ๋Š” ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ ๊ตฌ์ถ•์„ ์œ„ํ•œ ์ •๋ณด๋ฅผ ๋‹ค๋ฃจ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ ์šฉํ•˜๊ธฐ ์ „์— ์šฐ์„  ํ…Œ์ŠคํŠธ๋ฅผ ์‰ฝ๊ฒŒ ๋„์™€์ค„ ํด๋ž˜์Šค๋ฅผ ๋จผ์ € ๋งŒ๋“ค์–ด ๋ณด์•˜๋‹ค.

์šฐ์„  ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ๋ณด๊ธฐ์ „์— ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๋ชฉ์ ์„ ์•Œ์•„๋ณด๊ฒ ๋‹ค. ํ•ด๋‹น ํด๋ž˜์Šค์˜ ๋ชฉ์ ์€ ํฌ๊ฒŒ 2๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค.

1. mockMvc๋ฅผ ์ƒ์„ฑํ•˜์—ฌ api ํ…Œ์ŠคํŠธ

์—ฌ๊ธฐ์„œ mockmvc๋ž€?

๊ณต์‹ ๋ฌธ์„œ์— ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค๋ช…๋˜์–ด์žˆ๋‹ค.

Main entry point for server-side Spring MVC test support.

ํ•ด์„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋œป์ด ๋œ๋‹ค.

์„œ๋ฒ„์ธก Spring MVC ํ…Œ์ŠคํŠธ ์ง€์›์„ ์œ„ํ•œ ์ฃผ์š” ์ง„์ž…์ 

๊ณต์‹ ๋ฌธ์„œ

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html

๊ทธ๋ž˜์„œ mockmvc์˜ ์—ญํ• ์€?

ํ…Œ์ŠคํŠธ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ด์ „์—๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ ํ›„ postman์„ ํ†ตํ•˜์—ฌ ์ง์ ‘ ํ•ด๋‹น api๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์›ํ•˜๋Š” ๊ฐ’์ด ๋‚˜ํƒ€๋‚˜๋Š”์ง€ ํ™•์ธํ•˜์˜€๋‹ค. ์ด๋Ÿฌํ•œ postman๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด mockMvc๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. http method์ค‘ get์„ ์‚ฌ์šฉํ• ์ง€ post๋ฅผ ์‚ฌ์šฉํ• ์ง€ ์„ ํƒํ•˜๊ณ  url์„ ์ž…๋ ฅํ•˜๊ณ  ํ•„์š”์‹œ ๋ฐ”๋””๋‚˜ query string์„ ํ†ตํ•ด ์ธ์ž๋ฅผ ๋„˜๊ฒจ์ค„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น ๊ฒฐ๊ณผ๊ฐ€ ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ๊ฒƒ์ธ๊ฐ€?

@SpringBootTest
@AutoConfigureMockMvc

mockmvc๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์œ„ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜์˜€๋‹ค.

@SpringBootTest ์–ด๋…ธํ…Œ์ด์…˜์ด๋ž€ ?

Spring Boot ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค.

์œ„ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด์„œ ์‹ค์ œ spring boot๊ฐ€ ์‹คํ–‰๋  ๋•Œ ๋“ฑ๋ก๋˜๋Š” bean๋“ค์ด ์‹ค์ œ ํ™˜๊ฒฝ์—์„œ ๋Œ์•„๊ฐ€๋“ฏ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ ์œ„๋กœ ๋ชจ๋‘ ์˜ฌ๋ผ๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค.

์žฅ์ 

  • ์‹ค์ œ์™€ ๊ฐ™์€ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ „์ฒด์ ์ธ flow๋ฅผ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ์ 

  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ •๊ณผ ๋“ฑ๋ก๋œ ๋ชจ๋“  Bean๋“ค์„ ๋กœ๋“œํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„์ด ์˜ค๋ž˜๊ฑธ๋ฆฐ๋‹ค. ์ด๋Ÿฌํ•œ ๋‹จ์  ๋•๋ถ„์— ๋Œ€๋Ÿ‰์˜ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๊ณณ์—์„œ๋Š” ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ํ…Œ์ŠคํŠธ ํ•œ๋‹ค๊ณ  ๋“ค์—ˆ๋‹ค.

@AutoConfigureMockMvc์ด๋ž€?

MockMvc์˜ ์ž๋™ ๊ตฌ์„ฑ์„ ํ™œ์„ฑํ™”ํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฃผ์„

mockMvc๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์†๋„๋ฅผ ๋†’์ด๊ธฐ ์œ„ํ•ด์„œ ํŠน์ • ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜์—ฌ์„œ ํ•ด๋‹น ๋ถ€๋ถ„๋งŒ ๋กœ๋“œํ•˜๋Š” ๋ฐฉ์‹๋„ ์žˆ์ง€๋งŒ ํ•ด๋‹น ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•ด๋ณด๋‹ค ๋นˆ ๋“ฑ๋ก ๋ฌธ์ œ ๋•Œ๋ฌธ์— ์œ„์˜ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜์—ฌ ๋ณด์•˜๋‹ค. ์‰ฝ๊ฒŒ๋งํ•ด mockMvc์˜ ๊ตฌ์„ฑ์„ ์ž๋™์œผ๋กœ ํ™œ์„ฑํ™” ํ•ด์ฃผ๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋‹ค.

์–ด๋…ธํ…Œ์ด์…˜์— ๊ด€ํ•œ ์„ค๋ช… ์ฐธ์กฐ

https://goddaehee.tistory.com/211

๊ทธ๋ฆฌ๊ณ  ์–ด๋…ธํ…Œ์ด์…˜ ์„ค์ •๊ณผ mockMvc์‚ฌ์šฉ์„ ์œ„ํ•œ ์ถ”๊ฐ€์ ์ธ ์„ค์ •์„ ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰ํ•˜์˜€๋‹ค.

fun applyEncodingFilter() {
    this.mockMvc = MockMvcBuilders
        .webAppContextSetup(this.ctx)
        .apply<DefaultMockMvcBuilder>(springSecurity())
        .addFilters<DefaultMockMvcBuilder>(
            CharacterEncodingFilter("UTF-8", true),
        ).build()

}

@BeforeEach
fun setUp() {
    applyEncodingFilter()
}

๋งค๋ฒˆ ์š”์ฒญํ•  ๋•Œ๋งˆ๋‹ค ์œ„์™€๊ฐ™์ด mockMvc๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋ฉฐ ๋Œ€ํ‘œ์ ์œผ๋กœ springSecurity ์„ค์ •๊ณผ UTF-8 ์ธ์ฝ”๋”ฉ ์„ค์ •์„ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค. ์œ„์™€๊ฐ™์ด ์ดˆ๊ธฐํ™” ํ•˜์ง€์•Š๊ณ  ๊ทธ๋ƒฅ mockMvc ์ƒ์„ฑ ์œ„์•  @Autowire๋ฅผ ๋ถ™์ด๊ณ  ์‹คํ–‰ํ•˜์—ฌ ๋ณด์•˜๋Š”๋ฐ ๋‚˜์ค‘์— ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•  ๋•Œ ํ…Œ์ŠคํŠธ ๋ผ๋ฆฌ ์ถฉ๋Œํ•˜์—ฌ ์‹คํŒจํ•˜๋Š” ์ผ€์ด์Šค๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์œ„์™€๊ฐ™์ด ๋งค๋ฒˆ ์ดˆ๊ธฐํ™” ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜์˜€๋‹ค.

2. ๊ถŒํ•œ์ด ํ•„์š”ํ•œ API ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด์„œ mock ์œ ์ € ์ƒ์„ฑ

ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋˜๋ฉด ์ข‹๊ฒ ์ง€๋งŒ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ API ๊ฐ™์€ ๊ฒฝ์šฐ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ž˜์„œ mock ์œ ์ € ์ฃผ์ž…์„ ์œ„ํ•œ ์„ค์ •์ด ํ•„์š”ํ•˜๋‹ค. mock์ด๋ผ๋Š” ๋‹จ์–ด๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ๋‹จ์–ด ๋œป ๊ทธ๋Œ€๋กœ ๊ถŒํ•œ์ด ํ•„์š”ํ•  ๊ฒฝ์šฐ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ์ž„์‹œ ์œ ์ €์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

mock ์œ ์ €๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ์œ„ํ•ด์„œ memberRepo์™€ passwordEncoder์˜ ์˜์กด์„ฑ์„ ์ฃผ์ž… ๋ฐ›๋Š”๋‹ค.

@Autowired
lateinit var memberRepo: MemberRepo

@Autowired
lateinit var passwordEncoder: PasswordEncoder

passwordEncoder๋Š” ์™œ ์‚ฌ์šฉํ•˜๋Š”์ง€ ์˜๋ฌธ์ด ๋“ค ์ˆ˜ ์žˆ๋‹ค. passwordEncoder๋ฅผ ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ์œ ์ € ์ •๋ณด๋ฅผ db์— ์ €์žฅํ•  ๋•Œ๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์•”ํ˜ธํ™” ํ•˜์—ฌ์„œ ์ €์žฅํ•˜์—ฌ์•ผ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์œ ์ €๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ @BeforeTransaction ์–ด๋…ธํ…Œ์ด์…˜๊ณผ @AfterTransaction ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•˜์˜€๋‹ค. ํ™œ์šฉํ•œ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ ์ด์ „์— ์œ ์ €๊ฐ€ ์ƒ์„ฑ๋˜์–ด์•ผ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

@BeforeTransaction ์˜ ๊ณต์‹ ์„ค๋ช…

@Transactional ์ฃผ์„์„ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์‹คํ–‰๋˜๋„๋ก ๊ตฌ์„ฑ๋œ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•ด ํŠธ๋žœ์žญ์…˜์ด ์‹œ์ž‘๋˜๊ธฐ ์ „์— ์ฃผ์„์ด ๋‹ฌ๋ฆฐ ๊ณต์šฉ void ๋ฉ”์†Œ๋“œ๊ฐ€ ์‹คํ–‰๋˜์–ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ…Œ์ŠคํŠธ ์ฃผ์„. ์Šˆํผํด๋ž˜์Šค์˜ @BeforeTransaction ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

@BeforeTransaction
fun setUpAccount() {
    val member = Member(
        email = "test@naver.com",
        password = passwordEncoder.encode("password"),
        nickname = "nicktest",
        username = "username",
        birthDate = LocalDate.now(),
        phone = "01012345678",
        phoneKey = "ewuifhiwefheih2423r",
        agePolicyConsent = true,
        servicePolicyConsent = true,
        personalInfoPolicyConsent = true,
        smsConsent = false,
        emailConsent = false
    )
    member.updateRole(Role.ADMIN)
    testMember = memberRepo.save(member)
}

@AfterTransaction
fun cleanUpAccount() {
    val member = memberRepo.findByEmail("test@naver.com")
    member?.let{memberRepo.delete(it)}
}

beforeTransaction ์–ด๋…ธํ…Œ์ด์…˜์˜ ์ด๋ฆ„๊ณผ ๊ฐ™์ด transaction์„ ๊ฑธ์–ด์ค˜์•ผ์ง€ ํ•ด๋‹น ๋ฉ”์†Œ๋“œ ์ด์ „์— ์‹คํ–‰๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์œ„์™€๊ฐ™์ด ์ƒ์„ฑํ•œ ์œ ์ € ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•„๋ž˜์™€ ๊ฐ™์ด WithUserDetails ์–ด๋…ธํ…Œ์ด์…˜์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

@WithUserDetails(testUser)

์ฐธ์กฐ ๋ธ”๋กœ๊ทธ

https://freedeveloper.tistory.com/471

profile
๊ฐœ๋ฐœ์— ์žฌ๋ฏธ๋ฅผ ๋Š๋ผ๋ฉฐ ๊พธ์ค€ํžˆ ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž ๊น€์ข…์™„ ์ž…๋‹ˆ๋‹ค.

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