Unit test - f-lab-edu/practice-mall GitHub Wiki

Unit test λ‹¨μœ„ν…ŒμŠ€νŠΈ, λ‹¨μœ„ν…ŒμŠ€νŠΈλž€ ꡬ성 μš”μ†Œ λ˜λŠ” λͺ¨λ“ˆ ν…ŒμŠ€νŠΈλŠ” μ˜ˆμƒλ˜λŠ” λ™μž‘μ„ κ²€μ¦ν•˜κΈ° μœ„ν•΄ 격리된 μ†ŒμŠ€ μ½”λ“œλ₯Ό ν…ŒμŠ€νŠΈν•˜λŠ” μ†Œν”„νŠΈμ›¨μ–΄ ν…ŒμŠ€νŠΈμ˜ ν•œ ν˜•νƒœμ΄λ‹€.

좜처

  • λ‹¨μœ„ν…ŒμŠ€νŠΈμ˜ λͺ©μ 
  1. μ½”λ“œμ˜ 정확성을 ν™•μΈν•œλ‹€.
  2. λͺ¨λ“  κΈ°λŠ₯κ³Ό 절차λ₯Ό ν…ŒμŠ€νŠΈν•œλ‹€.
  3. 개발 μ£ΌκΈ° μ΄ˆκΈ°μ— 버그λ₯Ό μˆ˜μ •ν•˜κ³  λΉ„μš©μ„ 절감
  • λ‹¨μœ„ν…ŒμŠ€νŠΈμ˜ μœ ν˜•

μˆ˜λ™ν…ŒμŠ€νŠΈμ™€ μžλ™ν™”ν…ŒμŠ€νŠΈκ°€ μžˆλ‹€.

  • λ‹¨μœ„ν…ŒμŠ€νŠΈ 3κ°€μ§€ 기법

Black Box Testing,White Box Testing,Gray Box Testing (μ •λ¦¬ν•„μš”)

  • μœ λ‹›ν…ŒμŠ€νŠΈ? ν†΅ν•©ν…ŒμŠ€νŠΈ?
  1. μœ λ‹› ν…ŒμŠ€νŠΈλŠ” μž‘μ€ λ‹¨μœ„μ˜ μ½”λ“œ, 주둜 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ ν…ŒμŠ€νŠΈν•˜λŠ” 데 μ‚¬μš© 반면, 톡합 ν…ŒμŠ€νŠΈλŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ—¬λŸ¬ ꡬ성 μš”μ†Œκ°€ ν•¨κ»˜ λ™μž‘ν•˜λŠ”μ§€λ₯Ό ν™•μΈν•˜λŠ” 데 μ‚¬μš©
  2. μœ λ‹› ν…ŒμŠ€νŠΈλŠ” λΉ λ₯΄κ²Œ μ‹€ν–‰λ˜λ©°, μ½”λ“œμ˜ μž‘μ€ 뢀뢄을 μ§‘μ€‘μ μœΌλ‘œ ν…ŒμŠ€νŠΈ, 톡합 ν…ŒμŠ€νŠΈλŠ” 전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ™μž‘μ„ ν™•μΈν•˜κΈ° λ•Œλ¬Έμ— μ‹€ν–‰ μ‹œκ°„μ΄ κΈΈμ–΄μ§ˆ 수 있음

Spring Boot μ—μ„œ ν…ŒμŠ€νŠΈ

μŠ€ν”„λ§ λΆ€νŠΈλŠ” μ΄λŸ¬ν•œ ν…ŒμŠ€νŠΈλ₯Ό μ‰½κ²Œ μž‘μ„±ν•  수 μžˆλŠ” λ‹€μ–‘ν•œ 도ꡬ와 μ–΄λ…Έν…Œμ΄μ…˜μ„ 제곡

@SpringBootTest :톡합 ν…ŒμŠ€νŠΈλ₯Ό μ‰½κ²Œ μž‘μ„±ν•  수 있게 ν•΄μ€Œ, λ‹¨μœ„ν…ŒμŠ€νŠΈ(μœ λ‹›ν…ŒμŠ€νŠΈ)와 λΆ„λ¦¬ν•΄μ•Όν•œλ‹€.

μœ λ‹›ν…ŒμŠ€νŠΈ μž‘μ„±

  1. μ½”λ“œμ˜ μž‘μ€ λ‹¨μœ„λ₯Ό ν…ŒμŠ€νŠΈν•˜λŠ” 데 μ‚¬μš©
  2. 주둜 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ ν…ŒμŠ€νŠΈ
  3. μ™ΈλΆ€ μ˜μ‘΄μ„±μ„ μ΅œμ†Œν™”ν•˜λŠ” 것이 μ€‘μš”

JUnit(μžλ°”μ—μ„œ μ‚¬μš©ν•˜λŠ” ν…ŒμŠ€νŠΈν”„λ ˆμž„μ›Œν¬)κ³Ό mock objects μ‚¬μš©ν•΄ μ½”λ“œλ₯Ό κ²©λ¦¬ν•˜μ—¬ ν…ŒμŠ€νŠΈν•  수 μžˆλ‹€. (μ™ΈλΆ€ μ˜μ‘΄μ„±μ„ λͺ¨ν‚Ήν•˜μ—¬ ν…ŒμŠ€νŠΈν•  수 있음)

[mock objects]

Mockito라이브러리 (μ™ΈλΆ€μ˜μ‘΄μ„±μ„ λͺ¨ν‚Ήν•˜μ—¬ ν…ŒμŠ€νŠΈν•  수 있게 함)λ₯Ό 톡해 λΉˆμ„ 동적λͺ¨μ˜λ‘œ ꡬ성

즉, Mockitoλ₯Ό μ‚¬μš©ν•΄ mapper λ‚˜ repositoryλ₯Ό λͺ¨ν‚Ήν•˜κ³  Junit λ₯Ό μ‚¬μš©ν•΄ κ²°κ³Όλ₯Ό κ²€μ¦ν•œλ‹€.

μ΄λŠ” DB의 접근을 μ΅œμ†Œν™”ν•  수 μžˆλ‹€.

[μœ λ‹›ν…ŒμŠ€νŠΈ 지원 클래슀] org.springframework.test.util

org.springframework.test.web

[ Mockito 라이브러리의 주석 ]

@Mock : λͺ¨μ˜ 객체 생성

@InjectMocks : ν…ŒμŠ€νŠΈλœ 객체에 λͺ¨μ˜ ν•„λ“œλ₯Ό μžλ™μœΌλ‘œ μ£Όμž…

@RunWith(MockitoJUnitRunner.class) :Mock 객체λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ JUnit4μ—μ„œ μ‚¬μš©

@ExtendWith(MockitoExtension.class):Mock 객체λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ JUnit5μ—μ„œ μ‚¬μš©

@MockBean : @Mock의 경우 단일 ν΄λž˜μŠ€μ™€ ν•΄λ‹Ή λ©”μ„œλ“œμ— μ΄ˆμ μ„ 맞좘 λ‹¨μœ„ν…ŒμŠ€νŠΈ ν•˜λŠ”κ²½μš° @MockBean은 ν†΅ν•©ν…ŒμŠ€νŠΈμ— 주둜 μ‚¬μš©λ˜λ©΄μ„œ 컨트둀러 λ‹¨μœ„ ν…ŒμŠ€νŠΈμ— μ‚¬μš©

! λ‹€λ₯Έ μ–΄λ…Έν…Œμ΄μ…˜ μΆ”κ°€ μ˜ˆμ •

@WebMvcTest :


ν†΅ν•©ν…ŒμŠ€νŠΈ μž‘μ„±

전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ μ‹€μ œ λ™μž‘μ„ ν™•μΈν•˜κΈ° μœ„ν•΄μ„œλŠ” 톡합 ν…ŒμŠ€νŠΈ (λ°μ΄ν„°λ² μ΄μŠ€, μ›Ή 계측, μ„œλΉ„μŠ€ 계측 등을 ν¬ν•¨ν•œ 전체 μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ λ™μž‘μ„ ν…ŒμŠ€νŠΈ)

μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆλ₯Ό λ„μ›Œμ•Όν•˜κΈ° λ•Œλ¬Έμ— μ‹œκ°„μ΄ μ†Œμš”

μŠ€ν”„λ§λΆ€νŠΈμ—μ„œλŠ” @SpringBootTest μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜μ—¬ 톡합 ν…ŒμŠ€νŠΈλ₯Ό μž‘μ„±ν•œλ‹€.

Controller , Service Unit Test

controller : μ»¨νŠΈλ‘€λŸ¬λŠ” λ“€μ–΄μ˜€λŠ” HTTP μš”μ²­μ„ μ²˜λ¦¬ν•˜κ³  HTTP 응닡을 λ³΄λ‚΄λŠ” 역할을 μ£Όλ‘œν•˜κΈ° λ•Œλ¬Έμ— μ˜¬λ°”λ₯Έ 경둜둜 μ μ ˆν•œ μž‘μ—…μ΄ ν˜ΈμΆœλ˜λŠ”μ§€ μž‘μ—…μ΄ μ˜¬λ°”λ₯Έ λ³΄κΈ°λ‚˜ 응닡 μœ ν˜•μ„ λ°˜ν™˜ν•˜λŠ”μ§€ ν™•μΈν•΄μ•Όν•œλ‹€.

service : μ„œλΉ„μŠ€λŠ” μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ˜ 핡심 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ κ΅¬ν˜„ν•˜κΈ°μ— κΈ°λŠ₯ ν…ŒμŠ€νŠΈ 각 λ©”μ„œλ“œμ—μ„œ μ˜¬λ°”λ₯Έ 데이터λ₯Ό λ°˜ν™˜ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€. λ˜ν•œ 데이터가 잘 λ³€κ²½λ˜λŠ”μ§€ ν™•μΈν•œλ‹€.

[controller μœ λ‹›ν…ŒμŠ€νŠΈμ‹œ μ‚¬μš©ν•΄μ•Όν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜]

@WebMvcTest : μŠ€ν”„λ§ MVC 계측 ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ, 컨트둀러 클래슀만 λ‘œλ“œν•˜μ—¬ ν…ŒμŠ€νŠΈν•˜κ³  κ΄€λ ¨λœ λ·°λ‚˜ λ°μ΄ν„°λ² μ΄μŠ€μ™€ 같은 λ‹€λ₯Έ λΉˆλ“€μ€ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.

@MockBean : μ˜μ‘΄μ„±μœΌλ‘œ λ“±λ‘λœ 빈인 경우 Mock 객체둜 λŒ€μ²΄ν•΄μ•Ό ν•˜λŠ”λ°, μ—¬κΈ°μ„œ @MockBean을 μ‚¬μš©

νŠΉμ • 컨트둀러의 λ™μž‘μ„ ν…ŒμŠ€νŠΈν•˜κ³ , κ΄€λ ¨λœ λΉˆλ“€μ„ Mock 객체둜 λŒ€μ²΄ν•˜μ—¬ ν…ŒμŠ€νŠΈ

(μ΄λ ‡κ²Œ μŠ€ν”„λ§μ»¨ν…μŠ€νŠΈμ— 빈이 λ™λ‘λœ 것을 μ‚¬μš©ν•˜λŠ” μ΄μœ λŠ” 컨트둀러의 μ—­ν•  λ•Œλ¬Έμ΄μ§€ μ•Šμ„κΉŒμ‹ΆμŒ -> 더 μ°Ύμ•„λ³Ό μ˜ˆμ • )

[Service μœ λ‹›ν…ŒμŠ€νŠΈμ‹œ μ‚¬μš©ν•΄μ•Όν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜]

@Mock : Mockito λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” Mock 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜ , κ°„λ‹¨νžˆ μƒμ„±λ˜κ³  μ›ν•˜λŠ” λ©”μ„œλ“œμ˜ λ™μž‘μ„ μ§€μ •, μŠ€ν”„λ§μ»¨ν…μŠ€νŠΈμ™€ 관계없이 μ‚¬μš©ν•  수 μžˆλŠ” μž₯점이 μžˆλ‹€.

@InjectMocks : μœ„ μ„€λͺ…κ³Ό 동일

  • @Mock 와 @MockBean 차이점 ν•œμ€„ 정리
    @Mock λŠ” Mockito λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œ μ œκ³΅ν•˜λŠ” Mock 객체λ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•œ μ–΄λ…Έν…Œμ΄μ…˜μ΄κ³  μŠ€ν”„λ§ μ»¨ν…μŠ€νŠΈμ— Mock 객체λ₯Ό λ“±λ‘ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ, μ‹€μ œλ‘œ 빈으둜 λ“±λ‘λ˜λ©° μŠ€ν”„λ§μ—μ„œ 관리

Controller

Service

@WebMvcTest, @SpringBootTest와 같은 ν…ŒμŠ€νŠΈλ₯Ό μ‚¬μš©ν•˜λ©΄ Serviceλ§Œμ„ ν…ŒμŠ€νŠΈν•˜κΈ°κ°€ μ–΄λ ΅κΈ° λ•Œλ¬Έμ— @ExtendWith(MockitoExtension.class) ν™œμš©ν•΄ Mockito λ₯Ό μ‚¬μš©ν•˜κ²Œ λœλ‹€.

  • Service 내에 μ˜μ‘΄ν•˜κ³  μžˆλŠ” Mapperλ₯Ό @Mock으둜 μ„ μ–Έν•˜λ©΄ Mapper Bean에 μ˜μ‘΄ν•˜μ§€ μ•Šκ³  ν…ŒμŠ€νŠΈκ°€ κ°€λŠ₯ν•΄μ§„λ‹€.
  • Service λ₯Ό @InjectMocks둜 μ„ μ–Έν•¨μœΌλ‘œμ¨, @Mock으둜 μ„ μ–Έλœ κ°€μ§œ 객체듀을 μ˜μ‘΄ν•œ Service 객체가 μƒμ„±λœλ‹€.

Mockito

[verify - 검증]

[ArgumentMatchers]

Mock testλ₯Ό μ§„ν–‰ν•˜λ©΄μ„œ ν•„μš”ν•œ 객체λ₯Ό mockingν•˜κ³ , κ·Έ 객체의 νŠΉμ • λ©”μ†Œλ“œκ°€ 싀행될 λ•Œ, μ–΄λ–€ 값을 λ°˜ν™˜ν•˜λŠ”μ§€ μ„€μ •ν•˜λŠ” 경우

Assertions