λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

Spring/Boost Course Web

3.2 Spring Test

1) Test κ°œμš”

1. ν…ŒμŠ€νŒ…μ΄λž€ 무엇인가?

μš”κ΅¬ν•˜λŠ” μˆ˜μ€€μ„ λ§Œμ‘±ν•˜λŠ”μ§€ ν™•μΈν•˜κΈ° μœ„ν•΄ 결함을 λ°œκ²¬ν•˜λŠ” 과정이라고 말할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

전톡적인 ν…ŒμŠ€νŒ… κ°œλ…μ€ μ‘μš© ν”„λ‘œκ·Έλž¨ λ˜λŠ” μ‹œμŠ€ν…œμ΄ 잘 μž‘λ™ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

ν˜„μž¬μ˜ ν…ŒμŠ€νŒ… κ°œλ…μ€ μ‚¬μš©μžμ˜ κΈ°λŒ€ μˆ˜μ€€κ³Ό μš”κ΅¬ 사항에 맞게 κ΅¬ν˜„λ˜κ³  λ™μž‘ν•˜λŠ”μ§€λ₯Ό ν™•μΈν•˜κ³  이λ₯Ό 톡해 결함을 λ°œκ²¬ν•˜κ³ ,

μ΅œμ’…μ μœΌλ‘œ 결함 데이터λ₯Ό κ·Όκ°„μœΌλ‘œ 개발 ν”„λ‘œμ νŠΈμ˜ 리슀크(Risk)에 λŒ€ν•œ 수치적인 νŒλ‹¨ κ·Όκ±°λ₯Ό

μ˜μ‚¬ κ²°μ •κΆŒμž(ν”„λ‘œμ νŠΈ κ΄€λ¦¬μž λ“±)μ—κ²Œ μ „λ‹¬ν•˜λŠ” 것을 λ§ν•©λ‹ˆλ‹€.

 

개발 ν”„λ‘œμ νŠΈ μ΄ˆκΈ°μ— 개발 쀑간 μ‚°μΆœλ¬Ό(Work products)을 ν…ŒμŠ€νŒ… κ΄€μ μ—μ„œ 리뷰(Review)ν•˜κ³ ,

ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€λ₯Ό 미리 λ§Œλ“œλŠ” κ³Όμ •μ—μ„œ 결함을 λ°œκ²¬ν•˜λŠ” μž‘μ—…(결함 예방 ν™œλ™)도 ν…ŒμŠ€νŒ… ν™œλ™μ˜

μ€‘μš”ν•œ 뢀뢄이라고 말할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

생각해 λ³΄μ„Έμš”. μ‚¬μš©μžμ—κ²Œ μ „ν˜€ ν•„μš”μ—†λŠ” 뢀뢄을 κ°œλ°œν•˜κ³  κ°œλ°œν•œ 뢀뢄을 ν…ŒμŠ€νŠΈν•œλ‹€λ©΄ 무의미 ν•˜μ§€ μ•Šμ„κΉŒμš”?

'μš”κ΅¬μ‚¬ν•­μ΄ 잘λͺ»λœκ²ƒ μ•„λ‹κΉŒ?'와 같은 리뷰가 μ€‘μš”ν• κΉŒμš”? 개발이 μ€‘μš”ν•œ κ²ƒμΌκΉŒμš”?

이 2가지 물음 μ€‘μ—μ„œ ν˜„μž¬μ˜ ν…ŒμŠ€νŒ…μ€ μ „μžκ°€ 더 μ€‘μš”ν•˜λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

 

ν”„λ‘œκ·Έλž¨μ„ κ°œλ°œν•˜κΈ° 전에 μš”κ΅¬μ‚¬ν•­ 등을 λ¦¬λ·°ν•˜λŠ” 것을 정적 ν…ŒμŠ€νŠΈλΌκ³  ν•˜κ³ ,

ν”„λ‘œκ·Έλž¨ 개발 이후에 μ‹€μ œ μ‹€ν–‰ν•˜λ©΄μ„œ ν…ŒμŠ€νŠΈν•˜λŠ” 것을 동적 ν…ŒμŠ€νŠΈλΌκ³  ν•©λ‹ˆλ‹€.

 

λ³Έ μˆ˜μ—…μ—μ„œλŠ” 정적 ν…ŒμŠ€νŠΈλ³΄λ‹€ 동적 ν…ŒμŠ€νŠΈλ₯Ό ν•˜λŠ” 방법에 μ’€ 더 초점이 맞좰져 μžˆμŠ΅λ‹ˆλ‹€.

2. μ†Œν”„νŠΈμ›¨μ–΄μ—μ„œ ν…ŒμŠ€νŠΈκ°€ ν•„μš”ν•œ 이유

μ†Œν”„νŠΈμ›¨μ–΄κ°€ μ˜¬λ°”λ₯΄κ²Œ λ™μž‘ν•˜μ§€ μ•ŠλŠ” 경우, λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

1) κΈˆμ „μ μΈ 손싀

2) μ‹œκ°„ λ‚­λΉ„

3) λΉ„μ¦ˆλ‹ˆμŠ€μ˜ 이미지 손상

4) λΆ€μƒμ΄λ‚˜ 사망

 

μ†Œν”„νŠΈμ›¨μ–΄κ°€ μ˜¬λ°”λ₯΄κ²Œ λ™μž‘ν•˜μ§€ μ•ŠλŠ”λ‹€κ³  ν•΄μ„œ λΆ€μƒμ΄λ‚˜ 사망을 ν•  수 μžˆλ‹€λŠ” λ¬Έμ œμ— λŒ€ν•΄ μ˜μ•„ν•΄ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ μ˜€λŠ˜λ‚ μ—λŠ” μš°μ£Όμ„ , λΉ„ν–‰κΈ°, μ„ λ°•, μžλ™μ°¨ λ“± λ‹€μ–‘ν•œ κ³³μ—μ„œ μ†Œν”„νŠΈμ›¨μ–΄κ°€ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— μ˜€λ™μž‘μ„ μΌμœΌν‚¬ 경우 μ‹€μ œλ‘œ λΆ€μƒμ΄λ‚˜ μ‚¬λ§κΉŒμ§€λ„ μΌμ–΄λ‚˜κ²Œ ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ, ν…ŒμŠ€νŒ…μ€ μ΄λŸ¬ν•œ μ†Œν”„νŠΈμ›¨μ–΄ μ‹œμŠ€ν…œμ˜ 문제λ₯Ό μ΅œμ†Œν™”κΈ° μœ„ν•΄ ν•„μš”ν•©λ‹ˆλ‹€.

3. μ†Œν”„νŠΈμ›¨μ–΄ κ²°ν•¨μ˜ 원인

μ†Œν”„νŠΈμ›¨μ–΄κ°€ 결함이 λ°œμƒν•˜λŠ” μ΄μœ λŠ” λ¬΄μ—‡μΌκΉŒμš”?

κ°œλ°œμžκ°€ 잘λͺ» μž‘μ„±ν•œ 였λ₯˜λ‘œ μΈν•˜μ—¬ 결함(Defects λ˜λŠ” Bug)이 λ°œμƒν•©λ‹ˆλ‹€.

결함이 μžˆλŠ” μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό μ‹€ν–‰ν•˜κ²Œ 되면 μž₯μ• (Failure)κ°€ λ°œμƒν•˜μ—¬ μ˜λ„ν•œλŒ€λ‘œ μ†Œν”„νŠΈμ›¨μ–΄κ°€ λ™μž‘ν•˜μ§€ μ•Šκ±°λ‚˜

λ˜λŠ” μ†Œν”„νŠΈμ›¨μ–΄κ°€ λ™μž‘ν•˜μ§€ μ•Šμ•„μ•Ό ν•˜λŠ” μƒν™©μ—μ„œ λ™μž‘ν•˜λŠ” λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

단, λͺ¨λ“  κ²°ν•¨μ˜ 원인이 인간이 λ²”ν•˜λŠ” 였λ₯˜ λ•Œλ¬Έλ§Œμ€ μ•„λ‹™λ‹ˆλ‹€.

 

인간이 였λ₯˜λ₯Ό λ²”ν•˜κΈ° 쉽기 λ•Œλ¬Έμ— λ°œμƒν•˜λŠ” 결함도 μžˆμ§€λ§Œ μ‹œκ°„μ μΈ μ••λ°•, λ³΅μž‘ν•œ μ½”λ“œ, κΈ°λ°˜ν™˜κ²½μ˜ λ³΅μž‘μ„±,

κΈ°μˆ μ΄λ‚˜ μ‹œμŠ€ν…œμ˜ λ³€κ²½, 그리고 μˆ˜λ§Žμ€ μ‹œμŠ€ν…œ μƒν˜Έκ°„μ˜ 연동 λ“±μ˜ 이유둜 λ°œμƒν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

4. μ†Œν”„νŠΈμ›¨μ–΄ 개발, μœ μ§€λ³΄μˆ˜, 운영 μ‹œ ν…ŒμŠ€νŒ…μ˜ μ—­ν• 

μ†Œν”„νŠΈμ›¨μ–΄λŠ” 개발이 μ™„λ£Œλ˜κ³  μ‹€μ œ ν™˜κ²½μ— 배포λ₯Ό ν•΄μ•Ό μš΄μ˜λ©λ‹ˆλ‹€.

μš΄μ˜λ˜λŠ” 도쀑에도 ν•΄λ‹Ή μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό 더 이상 μ‚¬μš©ν•˜μ§€ μ•Šμ„ λ•ŒκΉŒμ§€ κ³„μ†ν•΄μ„œ μœ μ§€λ³΄μˆ˜λ₯Ό ν•˜κ²Œ λ©λ‹ˆλ‹€.

ν…ŒμŠ€νŒ…μ€ 개발 μ‹œμ—λ§Œ ν•„μš”ν•œ 것이 μ•„λ‹ˆλΌ 개발, μœ μ§€λ³΄μˆ˜, 운영 μ‹œμ— λͺ¨λ‘ ν•„μš”ν•©λ‹ˆλ‹€.

 

κ·Έλ ‡λ‹€λ©΄ ν…ŒμŠ€νŠΈκ°€ μ–Έμ œ ν•„μš”ν•œμ§€ μ•Œμ•„λ³ΌκΉŒμš”?

1) ν…ŒμŠ€νŒ…μ„ 톡해 릴리즈 전에 λ°œκ²¬λ˜μ§€ μ•Šμ€ 결함듀이 μˆ˜μ •λœλ‹€λ©΄, 운영 ν™˜κ²½ λ‚΄μ—μ„œ λ°œμƒν•˜λŠ” 리슀크(risk)λ₯Ό μ€„μ΄λŠ”λ° κΈ°μ—¬ν•  수 있으며 μ†Œν”„νŠΈμ›¨μ–΄ ν’ˆμ§ˆμ— 도움을 μ€λ‹ˆλ‹€.

2) ν…ŒμŠ€νŒ…μ€ 개발 초기의 μš”κ΅¬μ‚¬ν•­ 뢄석 단계뢀터 리뷰 및 μΈμŠ€νŽ™μ…˜μ„ 톡해 μ •μ μœΌλ‘œ μ΄λ€„μ§ˆ 수 있으며 각각의 개발 단계에 λŒ€μ‘ν•˜λŠ” ν…ŒμŠ€νŠΈ 레벨(test level)에 λ”°λ₯Έ ν…ŒμŠ€νŒ…μ΄ μ΄λ€„μ§‘λ‹ˆλ‹€.

3) 기쑴에 μš΄μ˜λ˜λŠ” μ†Œν”„νŠΈμ›¨μ–΄ μ‹œμŠ€ν…œμ΄ μœ μ§€ 보수 ν™œλ™μœΌλ‘œ λ³€κ²½ 및 λ‹¨μ’…λ˜κ±°λ‚˜ ν™˜κ²½μ΄ λ³€ν•˜λŠ” 경우, λ³€κ²½λœ μ†Œν”„νŠΈμ›¨μ–΄μ— λŒ€ν•œ ν…ŒμŠ€νŒ…κ³Ό λ³€κ²½λœ ν™˜κ²½μ—μ„œμ˜ 운영 ν…ŒμŠ€νŒ…μ΄ μš”κ΅¬λ©λ‹ˆλ‹€.

4) μ†Œν”„νŠΈμ›¨μ–΄ ν…ŒμŠ€νŒ…μ€ 계약상(법적) μš”κ΅¬μ‘°κ±΄λ“€, λ˜λŠ” 산업에 νŠΉν™”λœ ν‘œμ€€λ“€μ„ λ§Œμ‘±μ‹œν‚€κΈ° μœ„ν•΄μ„œ ν•„μš”ν•©λ‹ˆλ‹€.

5. ν…ŒμŠ€νŒ…κ³Ό ν’ˆμ§ˆ

ν…ŒμŠ€νŒ…μœΌλ‘œ 발견된 결함이 μ†Œμˆ˜μ΄κ±°λ‚˜ 없을 κ²½μš°μ— μ†Œν”„νŠΈμ›¨μ–΄μ˜ ν’ˆμ§ˆμ— λŒ€ν•œ ν™•μ‹ (Confidence)λ₯Ό κ°€μ§€κ²Œ λ©λ‹ˆλ‹€.

잘 μ„€κ³„λœ ν…ŒμŠ€νŠΈλŠ” μ‹œμŠ€ν…œμ˜ μ „λ°˜μ μΈ 리슀크λ₯Ό κ°μ†Œμ‹œν‚€κ³  결함을 λ°œκ²¬ν•©λ‹ˆλ‹€.

발견된 결함이 μˆ˜μ •λ  λ•Œ μ†Œν”„νŠΈμ›¨μ–΄ μ‹œμŠ€ν…œμ˜ ν’ˆμ§ˆ μ¦κ°€λ©λ‹ˆλ‹€.

 

ν’ˆμ§ˆμ„ 높이기 μœ„ν•΄μ„œλŠ” 이전 ν”„λ‘œμ νŠΈλ₯Ό 톡해 λ§Žμ€ ν…ŒμŠ€νŒ… κ²½ν—˜κ³Ό 정보λ₯Ό 확보할 ν•„μš”μ„±μ΄ μžˆμŠ΅λ‹ˆλ‹€.

λ‹€λ₯Έ ν”„λ‘œμ νŠΈμ—μ„œ 발견된 κ²°ν•¨μ˜ 근본적인 원인에 λŒ€ν•œ μ΄ν•΄ν•¨μœΌλ‘œμ¨ ν”„λ‘œμ„ΈμŠ€λ₯Ό κ°œμ„ ν•  수 있으며,

κ·ΈλŸ¬ν•œ κ²°ν•¨μ˜ μž¬λ°œμ„ λ°©μ§€ν•¨μœΌλ‘œμ¨, 결과적으둜, μ°¨ν›„ μ‹œμŠ€ν…œμ˜ ν’ˆμ§ˆμ„ κ°œμ„ ν•  수 있게 λ©λ‹ˆλ‹€.

 

개발 ν‘œμ€€μ΄λ‚˜ ꡐ윑 ν›ˆλ ¨ 그리고 결함 뢄석 λ“±κ³Ό ν•¨κ»˜ ν…ŒμŠ€νŒ…μ€ ν’ˆμ§ˆ 보증 ν™œλ™μ˜ ν•˜λ‚˜λ‘œ

ν…ŒμŠ€νŒ…μ„ 톡해 μ†Œν”„νŠΈμ›¨μ–΄ μ‹œμŠ€ν…œμ˜ ν’ˆμ§ˆμ„ 확보할 수 μžˆμŠ΅λ‹ˆλ‹€.

6. ν…ŒμŠ€νŒ…μ€ μ–Όλ§ˆλ‚˜ ν•΄μ•Ό μΆ©λΆ„ν•œκ°€?

κ·Έλ ‡λ‹€λ©΄ ν…ŒμŠ€νŒ…μ€ μ–Όλ§ˆλ‚˜ ν•΄μ•Ό μΆ©λΆ„ν•˜λ‹€κ³  말할 수 μžˆμ„κΉŒμš”?

μ–΄λŠ 정도 ν…ŒμŠ€νŒ… ν•˜λŠ” 것이 μ μ ˆν•œμ§€λ₯Ό νŒŒμ•…ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ‹€μŒκ³Ό 같은 리슀크(Risk) μˆ˜μ€€κ³Ό

ν”„λ‘œμ νŠΈ μ œμ•½μ‚¬ν•­μ„ κ³ λ €ν•΄μ•Όν•©λ‹ˆλ‹€.

 

1) 기술적인 λ‚΄μš©

2) λΉ„μ¦ˆλ‹ˆμŠ€ μ œν’ˆ

3) ν”„λ‘œμ νŠΈ 리슀크

4) μ‹œκ°„κ³Ό λΉ„μš©

 

ν…ŒμŠ€νŠΈλŠ” 개발 ν”„λ‘œμ νŠΈ κ΄€λ ¨μžλ“€μ΄ ν…ŒμŠ€νŠΈλœ μ†Œν”„νŠΈμ›¨μ–΄λ‚˜ μ‹œμŠ€ν…œμ˜ λ‹€μŒ 개발 λ‹¨κ³„λ‘œμ˜ 릴리즈(Release)에 λŒ€ν•œ κ²°μ • λ˜λŠ” κ³ κ°μ—κ²Œ 이양(Handover)ν•˜λŠ” λ¦΄λ¦¬μ¦ˆμ— λŒ€ν•œ 결정을 내릴 수 μžˆλ„λ‘ μΆ©λΆ„ν•œ 정보λ₯Ό μ œκ³΅ν•΄μ•Ό ν•©λ‹ˆλ‹€.

7. ν…ŒμŠ€νŒ…μ˜ 일반적인 원리

λ‹€μˆ˜μ˜ ν…ŒμŠ€νŒ…μ˜ 원리가 40μ—¬λ…„κ°„ μ œμ•ˆλ˜μ–΄ μ™”μœΌλ©° ν…ŒμŠ€νŒ…μ˜ μ›λ¦¬λŠ” ν…ŒμŠ€νŒ… μ „λ°˜μ— λŒ€ν•œ

일반적인 κ°€μ΄λ“œ 라인 역할을 ν•΄μ˜€κ³  μžˆμŠ΅λ‹ˆλ‹€.

 

원리 1 – ν…ŒμŠ€νŒ…μ€ 결함이 μ‘΄μž¬ν•¨μ„ λ°νžˆλŠ” ν™œλ™μ΄λ‹€.

ν…ŒμŠ€νŒ…μ€ 결함이 μ‘΄μž¬ν•¨μ„ λ“œλŸ¬λ‚΄μ§€λ§Œ, 결함이 μ—†λ‹€λŠ” 것을 증λͺ…ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

즉, ν”„λ‘œκ·Έλž¨μ΄ μ™„λ²½ν•˜λ‹€κ³  증λͺ…ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

μ΄λŠ” ν…ŒμŠ€νŠΈ ν•œ λΆ€λΆ„κΉŒμ§€λ§Œ 잘 λ™μž‘ν•œλ‹€κ³  말할 수 있고 ν…ŒμŠ€νŠΈλ₯Ό ν•˜μ§€ μ•Šμ€ 뢀뢄은

결함 μžˆλŠ”μ§€ λ˜λŠ” μ—†λŠ”μ§€μ— λŒ€ν•΄μ„œ μ˜ˆμΈ‘ν•  수 μ—†λ‹€λŠ” μ˜λ―Έμž…λ‹ˆλ‹€.

 

원리 2 – μ™„λ²½ν•œ ν…ŒμŠ€νŒ…(Exhaustive testing)은 λΆˆκ°€λŠ₯ν•˜λ‹€.

λͺ¨λ“  κ°€λŠ₯μ„±(μž…λ ₯κ³Ό 사전 쑰건의 λͺ¨λ“  μ‘°ν•©)을 ν…ŒμŠ€νŒ…ν•˜λŠ” 것은 μ§€κ·Ήνžˆ κ°„λ‹¨ν•œ μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό μ œμ™Έν•˜κ³  κ°€λŠ₯ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

보톡 λ‹€μŒκ³Ό 같은 이유 λ•Œλ¬Έμž…λ‹ˆλ‹€.

-  ν•œ ν”„λ‘œκ·Έλž¨ λ‚΄μ˜ λ‚΄λΆ€ 쑰건이 무수히 많음. (λ¬΄ν•œ 경둜)

-  μž…λ ₯이 κ°€μ§ˆ 수 μžˆλŠ” λͺ¨λ“  κ°’μ˜ 쑰건이 무수히 많음 (λ¬΄ν•œ μž…λ ₯ κ°’)

-  GUI 이벀트 λ°œμƒ μˆœμ„œμ— λŒ€ν•œ 쑰합도 무수히 많음 (λ¬΄ν•œ 타이밍)

μ™„λ²½ν•œ ν…ŒμŠ€νŒ… λŒ€μ‹ , 리슀크 뢄석과 κ²°μ •λœ μš°μ„ μˆœμœ„μ— 따라 ν…ŒμŠ€νŒ… ν™œλ™ λ…Έλ ₯을 μ§‘μ€‘μ‹œμΌœμ•Ό ν•©λ‹ˆλ‹€. (Risk-based testing)

μ™„λ²½ν•œ ν…ŒμŠ€νŒ…μ€ μš°μ£Όν•­κ³΅, 의료 λ“± μ•ˆμ „μ΄ μ΅œμš°μ„ (Safety critical)인 μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό κ°œλ°œν•  λ•Œ κ³ λ €ν•  수 μžˆμœΌλ‚˜

μ‹€μ œλ‘œ μ™„λ²½ν•œ 것은 μ•„λ‹ˆκ³  κ°•λ ₯ν•œ ν…ŒμŠ€νŒ…μœΌλ‘œ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

 

원리 3 – ν…ŒμŠ€νŒ…μ„ 개발 μ΄ˆκΈ°μ— μ‹œμž‘ν•œλ‹€.

ν…ŒμŠ€νŒ… ν™œλ™μ€ μ†Œν”„νŠΈμ›¨μ–΄λ‚˜ μ‹œμŠ€ν…œ 개발 수λͺ…μ£ΌκΈ°μ—μ„œ κ°€λŠ₯ν•œ μ΄ˆκΈ°μ— μ‹œμž‘λ˜μ–΄μ•Ό ν•˜λ©°,

μ„€μ •ν•œ ν…ŒμŠ€νŒ… λͺ©ν‘œμ— 집쀑해야 ν•©λ‹ˆλ‹€.

개발 μ΄ˆκΈ°μ— ν…ŒμŠ€νŒ…μ„ μ‹œμž‘ν•œλ‹€λŠ” κ²ƒμ˜ μ˜λ―ΈλŠ” 개발의 μ‹œμž‘κ³Ό λ™μ‹œμ— ν…ŒμŠ€νŠΈλ₯Ό κ³„νšν•˜κ³ 

μ „λž΅μ μœΌλ‘œ μ ‘κ·Όν•˜λŠ” 것을 κ³ λ €ν•˜λŠ” 것은 λ¬Όλ‘ , μš”κ΅¬μ‚¬ν•­ λΆ„μ„μ„œμ™€ μ„€κ³„μ„œ λ“±μ˜ 개발 쀑간 μ‚°μΆœλ¬Όμ„ λΆ„μ„ν•˜μ—¬

ν…ŒμŠ€νŠΈν•˜λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

 

+ν…ŒμŠ€νŒ…μ΄ μ€‘μš”ν•˜λ‹€λ³΄λ‹ˆ TDD같은 방법둠도 μ‘΄μž¬ν•©λ‹ˆλ‹€. TDDκ°€ 무엇인지 μ•Œμ•„λ³΄μ„Έμš”. γ…‘> spring-boot κ°•μ˜μ— μ΄μ–΄μ„œ 배우고 있음.


2) JUnit

1. JUnitμ΄λž€?

ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ§ˆλ‹€ ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•œ ν”„λ ˆμž„μ›Œν¬κ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ 도ꡬ듀을 보톡 xUnit이라고 λ§ν•©λ‹ˆλ‹€. μžλ°”μ–Έμ–΄μ˜ κ²½μš°λŠ” JUnit이라고 λ§ν•©λ‹ˆλ‹€.

각 μ–Έμ–΄λ§ˆλ‹€ μ‚¬μš©λ˜λŠ” xUnit은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

 

img

2. JUnit μ‚¬μš©ν•˜κΈ°

JUnit을 μ‚¬μš©ν•˜λ €λ©΄ JUnit λΌμ΄λΈŒλŸ¬λ¦¬κ°€ 클래슀패슀(CLASSPATH)에 μ‘΄μž¬ν•΄μ•Ό ν•©λ‹ˆλ‹€.

직접 λ‹€μš΄λ‘œλ“œλ₯Ό λ°›λŠ” 것은 번거둭기 λ•Œλ¬Έμ— 보톡 λΉŒλ“œ 도ꡬ인 Mavenμ΄λ‚˜ Gradle을 μ΄μš©ν•΄ λ‹€μš΄λ‘œλ“œ λ°›μ•„ μ‚¬μš©ν•©λ‹ˆλ‹€.

Maven을 μ‚¬μš©ν•  경우 pom.xml에 λ‹€μŒμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

3) μŠ€ν”„λ§ ν…ŒμŠ€νŠΈ μ–΄λ…Έν…Œμ΄μ…˜ μ‚¬μš©ν•˜κΈ°

ν”„λ‘œμ νŠΈλͺ…: calculatorcli02

 

이전 μ‹œκ°„μ— ν•™μŠ΅ν–ˆλ˜ 사칙연산을 κ³„μ‚°ν•˜λŠ” CalculatorService클래슀λ₯Ό μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œ 빈(Bean)으둜 κ΄€λ¦¬λ˜λ„λ‘ μˆ˜μ •ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

그리고 λ‚˜μ„œ κΈ°μ‘΄ ν…ŒμŠ€νŠΈ ν΄λž˜μŠ€λ„ μˆ˜μ •ν•˜μ—¬ 빈(Bean)을 ν…ŒμŠ€νŠΈ ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

1. μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λ„λ‘ κΈ°μ‘΄ μ½”λ“œ λ³€κ²½ν•˜κΈ°

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ κ΄€λ ¨ λΌμ΄λΈŒλŸ¬λ¦¬λ“€μ΄ ν”„λ‘œμ νŠΈμ— μΆ”κ°€ λ˜μ•Ό ν•©λ‹ˆλ‹€.

pom.xml νŒŒμΌμ„ μˆ˜μ •ν•©λ‹ˆλ‹€.

μˆ˜μ •μ„ ν•˜κ³  λ‚˜μ„œ Maven updateλ₯Ό μˆ˜ν–‰ν•©λ‹ˆλ‹€.

μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λ₯Ό μ‚¬μš©ν•˜λ €λ©΄ μ„€μ • νŒŒμΌμ„ μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€. μŠ€ν”„λ§ μ„€μ • νŒŒμΌμ€ xmlνŒŒμΌμ΄λ‚˜ Java Config둜 μž‘μ„±ν•  수 μžˆλ‹€κ³  ν•˜μ˜€μŠ΅λ‹ˆλ‹€. Java Config파일둜 λ‹€μŒκ³Ό 같이 μž‘μ„±ν•΄ 보도둝 ν•˜κ² μŠ΅λ‹ˆλ‹€.

 

ApplicationConfig.java

package org.edwith.webbe.calculatorcli;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration // λ‚˜ μŠ€ν”„λ§ μ„€μ • νŒŒμΌμ΄μ•Ό. μŠ€ν”„λ§ μ„€μ •νŒŒμΌμ€ μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆμΈ ApplicationContextμ—μ„œ 읽어듀인닀
@ComponentScan(basePackages = {"org.edwith.webbe.calculatorcli"}) //νŠΉμ • νŒ¨ν‚€μ§€ μ΄ν•˜μ—μ„œ @Component, @Repository, @Service, @Controller, @RestController λ“±μ˜ μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 클래슀λ₯Ό μ°Ύμ•„ 빈으둜 λ“±λ‘ν•©λ‹ˆλ‹€.
public class ApplicationConfig {
}

 

CalculatorService.java

package org.edwith.webbe.calculatorcli;

import org.springframework.stereotype.Component;

//μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆμ—μ„œ κ΄€λ¦¬ν•œλ‹€λŠ” 것은 κ°œλ°œμžκ°€ 직접 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
//μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ μΈμŠ€ν„΄μŠ€λ₯Ό 생성해 κ΄€λ¦¬ν•œλ‹€λŠ” 것을 λœ»ν•©λ‹ˆλ‹€.
@Component // μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ CalculatorService클래슀λ₯Ό μ°Ύμ•„ 빈으둜 등둝할 수 μžˆλ„λ‘ μ–΄λ…Έν…Œμ΄μ…˜.
public class CalculatorService {
    public int plus(int value1, int value2) {
        return value1 + value2;
    }

    public int minus(int value1, int value2) {
        return value1 - value2;
    }

    public int multiple(int value1, int value2) {
        return value1 * value2;
    }

    public int divide(int value1, int value2) throws ArithmeticException {
        return value1 / value2;
    }
}

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆμ—μ„œ κ΄€λ¦¬ν•œλ‹€λŠ” 것은 κ°œλ°œμžκ°€ 직접 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ μΈμŠ€ν„΄μŠ€λ₯Ό 생성해 κ΄€λ¦¬ν•œλ‹€λŠ” 것을 λœ»ν•©λ‹ˆλ‹€.

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ CalculatorService클래슀λ₯Ό μ°Ύμ•„ 빈으둜 등둝할 수 μžˆλ„λ‘ 클래슀 μœ„μ— @Componentλ₯Ό λΆ™μž…λ‹ˆλ‹€.

 

μœ„μ™€ 같이 μž‘μ„±ν–ˆλ‹€λ©΄, κΈ°μ‘΄ 클래슀λ₯Ό μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œ μ‚¬μš©λ  μ€€λΉ„κ°€ λλ‚œ κ²ƒμž…λ‹ˆλ‹€.

CalculatorService 클래슀λ₯Ό μ΄μš©ν•˜λ €λ©΄ λ‹€μŒκ³Ό 같은 클래슀λ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€.

 

Main.java

package org.edwith.webbe.calculatorcli;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
  public static void main(String[] args){
   ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);

   CalculatorService calculatorService = applicationContext.getBean(CalculatorService.class);
   System.out.println(calculatorService.plus(10, 50)); // result: 60
  }
}

2. ν…ŒμŠ€νŠΈ 클래슀λ₯Ό μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‚¬μš©ν•˜λ„λ‘ μˆ˜μ •ν•˜κΈ°

κΈ°μ‘΄ ν…ŒμŠ€νŠΈ ν΄λž˜μŠ€λŠ” ν…ŒμŠ€νŠΈν•  객체λ₯Ό @Beforeκ°€ 뢙은 λ©”μ†Œλ“œμ—μ„œ μ΄ˆκΈ°ν™” ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆλ₯Ό μ‚¬μš©ν•  λ•ŒλŠ” κ°œλ°œμžκ°€ 직접 μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜λ©΄ μ•ˆλ©λ‹ˆλ‹€.

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ λΉˆμ„ μƒμ„±ν•˜κ³  κ΄€λ¦¬ν•˜λ„λ‘ ν•˜κ³ , κ·Έ λΉˆμ„ ν…ŒμŠ€νŠΈ ν•΄μ•Όν•©λ‹ˆλ‹€.

이λ₯Ό μœ„ν•΄μ„œ μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬λŠ” λͺ‡κ°€μ§€ νŠΉλ³„ν•œ κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€. μ†ŒμŠ€ μ½”λ“œλ₯Ό μ•„λž˜μ™€ 같이 μˆ˜μ •ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.

 

κΈ°μ‘΄ ν…ŒμŠ€νŠΈ 클래슀 μœ„μ— @RunWith(SpringJUnit4ClassRunner.class)λ₯Ό λΆ™μž…λ‹ˆλ‹€.

@RunWith μ–΄λ…Έν…Œμ΄μ…˜μ€ JUnit이 μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μž…λ‹ˆλ‹€.

JUnit은 ν™•μž₯κΈ°λŠ₯을 κ°€μ§€λŠ”λ°, μŠ€ν”„λ§μ—μ„œλŠ” JUnit을 ν™•μž₯ν•˜λ„λ‘ SpringJUnit4ClassRunner.classλ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€.

ν•΄λ‹Ή μ½”λ“œλŠ” JUnit이 ν…ŒμŠ€νŠΈ μ½”λ“œλ₯Ό μ‹€ν–‰ν•  λ•Œ μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ λ‚΄λΆ€μ μœΌλ‘œ μƒμ„±λ˜λ„λ‘ ν•©λ‹ˆλ‹€.

 

@ContextConfiguration(classes = {ApplicationConfig.class})은 λ‚΄λΆ€μ μœΌλ‘œ μƒμ„±λœ μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆκ°€ μ‚¬μš©ν•  μ„€μ •νŒŒμΌμ„ 지정할 λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

 

μœ„μ—μ„œ μ„€λͺ…ν•œ 2쀄이 ν…ŒμŠ€νŠΈ 클래슀 μœ„μ— 있으면, ν…ŒμŠ€νŠΈ 클래슀 μžμ²΄κ°€ 빈(Bean)객체가 λ˜μ–΄ μŠ€ν”„λ§μ—μ„œ κ΄€λ¦¬λ˜κ²Œ λ©λ‹ˆλ‹€.

 

@Autowired

CalculatorService calculatorService;

CalcultorServiceTest ν΄λž˜μŠ€κ°€ 빈으둜 κ΄€λ¦¬λ˜λ©΄μ„œ, μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆλŠ” CalculatorServiceλ₯Ό

μ£Όμž…(Inject)ν•  수 있게 λ©λ‹ˆλ‹€. μ΄λ ‡κ²Œ μ£Όμž…λœ 클래슀λ₯Ό ν…ŒμŠ€νŠΈν•˜λ©΄ λ©λ‹ˆλ‹€.

 

ν…ŒμŠ€νŠΈ κ²°κ³ΌλŠ” 기쑴의 ν΄λž˜μŠ€μ™€ 같은 것을 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.


4) 둜직 λ‹¨μœ„ν…ŒμŠ€νŠΈ κ΅¬ν˜„ν•˜κΈ°

λΉˆλ“€ κ°„μ—λŠ” λ‹€μ–‘ν•œ 관계λ₯Ό λ§Ίκ³  μžˆλŠ” κ²½μš°κ°€ λ§ŽμŠ΅λ‹ˆλ‹€.

ν•˜λ‚˜μ˜ λΉˆμ„ μ‚¬μš©ν•œλ‹€λŠ” 것은 κ΄€κ³„λœ λΉˆλ“€λ„ ν•¨κ»˜ λ™μž‘ν•œλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.

 

톡합 ν…ŒμŠ€νŠΈ(integration test): ν•˜λ‚˜μ˜ λΉˆμ„ ν…ŒμŠ€νŠΈν•  λ•Œ κ΄€λ ¨λœ λΉˆλ“€μ΄ λͺ¨λ‘ 잘 λ™μž‘ν•˜λŠ”μ§€ ν…ŒμŠ€νŠΈν•˜λŠ” 것

λ‹¨μœ„ ν…ŒμŠ€νŠΈ(unit test): κ΄€κ³„λœ λ‹€λ₯Έ ν΄λž˜μŠ€μ™€λŠ” 상관 없이 νŠΉμ • 빈이 가지고 μžˆλŠ” κΈ°λŠ₯만 잘 λ™μž‘ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” 것

 

MyService.java

package org.edwith.webbe.calculatorcli;
import org.springframework.stereotype.Service;

@Service
public class MyService {
     private final CalculatorService calculatorService;
     public MyService(CalculatorService calculatorService) {
          this.calculatorService = calculatorService;
     }
     public int execute(int value1, int value2) {
    //  return 0;
          return calculatorService.plus(value1, value2) * 2;
    }
}

MyServiceν΄λž˜μŠ€λŠ” μ•„λž˜μ˜ 클래슀 λ‹€μ΄μ–΄κ·Έλž¨μ²˜λŸΌ CalculatorServiceλ₯Ό ν•„λ“œλ‘œ 가지고 μžˆμŠ΅λ‹ˆλ‹€.

ν•΄λ‹Ή ν•„λ“œλŠ” μƒμ„±μžλ₯Ό 톡해 μ΄ˆκΈ°ν™”λ₯Ό ν•©λ‹ˆλ‹€.

img

MyServiceκ°€ 가지고 μžˆλŠ” executeλ©”μ†Œλ“œλŠ” calculatorService.plus()λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

2개의 값을 λ°›μ•„ plus()λ©”μ†Œλ“œλ₯Ό μ΄μš©ν•΄ λ”ν•œ ν›„ 2λ₯Ό λ”ν•œ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

 

μ΄λ ‡κ²Œ μž‘μ„±ν•œ MyServiceκ°μ²΄λŠ” λ‹€μŒκ³Ό 같은 λ°©λ²•μœΌλ‘œ ν…ŒμŠ€νŠΈλ₯Ό ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

MyServiceTest.java

package org.edwith.webbe.calculatorcli;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationConfig.class})
public class MyServiceTest {
    @Autowired
    MyService myService;

    @Test
    public void execute() throws Exception{
        // given
        int value1 = 5;
        int value2 = 10;

        // when
        int result = myService.execute(value1, value2);

        // then
        Assert.assertEquals(30, result);
    }
}

@RunWith(SpringJUnit4ClassRunner.class) λŠ” λ‚΄λΆ€μ μœΌλ‘œ μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆλ₯Ό μƒμ„±ν•œλ‹€κ³  ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

μŠ€ν”„λ§ 빈 μ»¨ν…Œμ΄λ„ˆλŠ” λΉˆλ“€μ„ μ°Ύμ•„ λ©”λͺ¨λ¦¬μ— 올리게 λ©λ‹ˆλ‹€. 그리고 λ‚˜μ„œ myServiceν•„λ“œμ— 객체λ₯Ό μ£Όμž…ν•˜κ²Œ λ©λ‹ˆλ‹€.

 

ν…ŒμŠ€νŠΈ λ©”μ†Œλ“œλŠ” myService.execute()λ₯Ό μ‹€ν–‰ν•©λ‹ˆλ‹€. 5와 10을 λ”ν•œ 값에 2λ₯Ό κ³±ν•œ κ²°κ³Όλ₯Ό exeucte()λ©”μ†Œλ“œλŠ” λ°˜ν™˜ν•©λ‹ˆλ‹€.

 

assertEquals()λ©”μ†Œλ“œλ‘œ λΉ„κ΅ν•œ κ²°κ³Ό, κ²°κ³ΌλŠ” 맞게 λ‚˜μ˜¬ 거라고 μ˜ˆμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

그런데, CalculatorService의 plus()λ©”μ†Œλ“œμ— 버그가 μžˆλ‹€λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

plus()λ©”μ†Œλ“œκ°€ λ”ν•˜λŠ” 것이 μ•„λ‹ˆλΌ κ³±ν•œ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•œλ‹€λ©΄ μ–΄λ–»κ²Œ λ κΉŒμš”?

μ•„λ§ˆ λ‚΄κ°€ μƒκ°ν•œ 값이 λ‚˜μ˜€μ§€ μ•Šμ„ κ²ƒμž…λ‹ˆλ‹€.

 

MyServiceλ₯Ό ν…ŒμŠ€νŠΈν•˜λ €κ³  ν•˜μ˜€μ§€λ§Œ CalculatorService의 λ²„κ·Έλ‘œ 인해 μ—λŸ¬κ°€ λ‚  μˆ˜λ„ μžˆλŠ” κ²ƒμž…λ‹ˆλ‹€. 이런 문제λ₯Ό ν•΄κ²°ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒμš”? 이런 문제λ₯Ό ν•΄κ²°ν•˜λŠ” 방법 쀑 ν•˜λ‚˜λŠ” λͺ©(Mock)객체λ₯Ό μ΄μš©ν•˜λŠ” 방법이 μžˆμŠ΅λ‹ˆλ‹€.

img

MyServiceκ°€ μ‚¬μš©ν•˜λ˜ CalculatorServiceλ₯Ό μ‚¬μš©ν•˜λŠ” λŒ€μ‹ , κ°€μ§œ 객체λ₯Ό ν•˜λ‚˜ μƒμ„±ν•˜λ„λ‘ ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. λ‚΄κ°€ μ›ν•˜λŠ” λ™μž‘μ„ ν•˜λŠ” Mock객체둜 CalculatorServiceλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ MyService의 λ‚΄μš©λ§Œ ν…ŒμŠ€νŠΈλ₯Ό μˆ˜ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

이λ₯Ό μœ„ν•΄ pom.xmlνŒŒμΌμ— λ‹€μŒμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.

<!-- test mock을 μœ„ν•œ 라이브러리λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€. -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
</dependency>

mockitoλŠ” λͺ¨κΈ°μ˜ μ˜μ–΄λ‹¨μ–΄λ₯Ό 쀄인 말이 μ•„λ‹ˆκ³  유λͺ…ν•œ μ˜ν™” λŒ€μ‚¬μΈ “λͺ¨νžˆλ˜ ν•œ μž”ν•˜λŸ¬ κ°€μž”의 λͺ¨νžˆν† μ—μ„œ 이름을 λ”°μ™”λ‹€κ³  ν•©λ‹ˆλ‹€.

mockitoλŠ” μ˜€ν”ˆμ†ŒμŠ€ λͺ© ν”„λ ˆμž„μ›Œν¬μž…λ‹ˆλ‹€.

ν…ŒμŠ€νŠΈλ₯Ό μœ„ν•΄ κ°€μ§œ 객체λ₯Ό μ‰½κ²Œ λ§Œλ“€μ–΄ 쀄 수 μžˆλŠ” ν”„λ ˆμž„μ›Œν¬λΌκ³  μƒκ°ν•˜λ©΄ νŽΈν•©λ‹ˆλ‹€.

img

Mockito ν”„λ ˆμž„μ›Œν¬ 자체만 ν•˜λ”λΌλ„ 닀뀄야 ν•  양이 λ§Žμ•„μ„œ Mockito에 λŒ€ν•΄ λͺ¨λ‘ λ‹€λ£¨κΈ°λŠ” μ–΄λ ΅μŠ΅λ‹ˆλ‹€.

이번 μ‹œκ°„μ€ Mockitoλ₯Ό μ΄μš©ν•΄ λͺ© 객체λ₯Ό μ‚¬μš©ν•˜λŠ” 것이 이런 κ²ƒμ΄κ΅¬λ‚˜λΌκ³  느끼게 λ§Œλ“œλŠ” 것이 λͺ©μ μž…λ‹ˆλ‹€.

 

MyServiceTest2.java

package org.edwith.webbe.calculatorcli;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.verify;

// mockitoκ°€ μ œκ³΅ν•˜λŠ” Junit ν™•μž₯ 클래슀 MockitoJunitRunnerλ₯Ό μ΄μš©ν•΄ ν…ŒμŠ€νŠΈ 클래슀λ₯Ό μ‹€ν–‰ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.
@RunWith(MockitoJUnitRunner.class)
public class MyServiceTest2 {

//    @InjectMocks μ–΄λ…Έν…Œμ΄μ…˜μ΄ 뢙은 ν•„λ“œλŠ” λͺ© 객체λ₯Ό μ‚¬μš©ν•˜λŠ” MyService 객체λ₯Ό μƒμ„±ν•˜μ—¬ μ΄ˆκΈ°ν™”ν•˜λΌλŠ” 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€. 
//    myService μ—­μ‹œ μ—¬λŸ¬λΆ„λ“€μ΄ μ΄ˆκΈ°ν™”ν•˜μ§€ μ•Šμ•„λ„ μžλ™μœΌλ‘œ MyService 객체가 μƒμ„±λ˜μ–΄ μ΄ˆκΈ°ν™” λ©λ‹ˆλ‹€.
    @InjectMocks
    MyService myService;

//    @Mock μ–΄λ…Έν…Œμ΄μ…˜μ€ calculatorServiceκ°€ λͺ© 객체λ₯Ό μ°Έμ‘°ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.
//    즉, μ—¬λŸ¬λΆ„μ΄ 객체λ₯Ό μƒμ„±ν•˜μ§€ μ•Šμ•„λ„ μžλ™μœΌλ‘œ 객체가 μƒμ„±λ˜κ³  ν•΄λ‹Ή ν•„λ“œκ°€ μ΄ˆκΈ°ν™” λœλ‹€λŠ” 것을 μ˜λ―Έν•©λ‹ˆλ‹€.
    @Mock
    CalculatorService calculatorService;

    @Test
    public void execute() throws Exception {
        // given
        int value1 = 5;
        int value2 = 10;
        given(calculatorService.plus(5, 10)).willReturn(15);
//        given()은 staticλ©”μ†Œλ“œμž…λ‹ˆλ‹€.
//        import문을 보면 org.mockito.BDDMockito 클래슀의 static λ©”μ†Œλ“œμΈκ²ƒμ„ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. 
//        calculatorServiceλŠ” κ°€μ§œ κ°μ²΄μž…λ‹ˆλ‹€. 이 κ°€μ§œ 객체가 λ™μž‘ν•˜λŠ” 방법을 κ·œμ •ν•  수 μžˆλŠ” 것이 given()λ©”μ†Œλ“œμž…λ‹ˆλ‹€.
//        calculatorService.plus(5,10)을 ν˜ΈμΆœν•˜λ©΄ plusλ©”μ†Œλ“œκ°€ 15λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ ν•˜λΌλŠ” 의미λ₯Ό κ°€μ§‘λ‹ˆλ‹€. 


        // when
        int result = myService.execute(value1, value2);
//        execute()λ©”μ†Œλ“œλŠ” λ‚΄λΆ€μ μœΌλ‘œ calculatorService의 plusλ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. 
//        ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” μœ„μ—μ„œ μ„€μ •ν•œλŒ€λ‘œλ§Œ λ™μž‘ν•©λ‹ˆλ‹€. 
//        value1κ³Ό value2κ°€ 무슨 값이든지 간에 resultλŠ” 30을 λ°˜ν™˜ν•  κ²ƒμž…λ‹ˆλ‹€.

        // then
        verify(calculatorService).plus(anyInt(), anyInt());
//        verify()λ©”μ†Œλ“œλŠ” org.mockito.Mockito의 staticν•œ λ©”μ†Œλ“œμž…λ‹ˆλ‹€. 
//        anyInt()λ©”μ†Œλ“œλŠ” org.mockito.Matchers의 staticν•œ λ©”μ†Œλ“œμž…λ‹ˆλ‹€. 
//        verifyλ©”μ†Œλ“œλŠ” νŒŒλΌλ―Έν„°λ‘œ λ“€μ–΄μ˜¨ 객체의 plusλ©”μ†Œλ“œκ°€ 호좜된 적이 μžˆλŠ”μ§€ κ²€μ¦ν•©λ‹ˆλ‹€.
//        μ’€ 더 μžμ„Ένžˆ μ‚΄νŽ΄λ³΄μžλ©΄ plus(anyInt(), anyInt())λŠ” μ–΄λ–€ μ •μˆ˜λ“ μ§€ 2개λ₯Ό νŒŒλΌλ―Έν„°λ‘œ λ„£μ–΄μ„œ
//        plus()λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν–ˆλŠ”μ§€λ₯Ό κ²€μ¦ν•©λ‹ˆλ‹€. 
//        myService.execute()λ©”μ†Œλ“œ λ‚΄λΆ€μ μœΌλ‘œ plus λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν–ˆλ‹€λ©΄ ν•΄λ‹Ή λ©”μ†Œλ“œλŠ” 검증을 μ„±κ³΅ν•œ κ²ƒμž…λ‹ˆλ‹€.
//        λ§Œμ•½, execute()λ©”μ†Œλ“œμ—μ„œ plus(anyInt(), anyInt())λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ 였λ₯˜κ°€ λ°œμƒν•˜κ²Œ λ©λ‹ˆλ‹€.
        Assert.assertEquals(30, result);
    }
}

execute() λ©”μ†Œλ“œλ₯Ό μœ„μ™€ 같이(plusλ©”μ†Œλ“œκ°€ ν˜ΈμΆœλ˜μ§€ μ•Šλ„λ‘ 주석문 μ²˜λ¦¬ν•˜μ˜€λ‹€.) μˆ˜μ •ν•œ ν›„ ν…ŒμŠ€νŠΈλ₯Ό μ‹€ν–‰ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

ν•΄λ‹Ή λ©”μ†Œλ“œκ°€ ν˜ΈμΆœν•œ 적 μ—†λ‹€λŠ” Exception이 λ°œμƒν•˜λ©΄ ν…ŒμŠ€νŠΈλŠ” μ‹€νŒ¨ν•œ κ²ƒμž…λ‹ˆλ‹€.

'Spring > Boost Course Web' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

4.2 Layered Architecture  (0) 2020.11.19
4.1 Spring MVC  (0) 2020.11.19
3.3 Spring JDBC  (0) 2020.11.19
3.1 Spring Core  (0) 2020.11.19
2.6 JSTL & EL  (0) 2020.11.19
2.5 Scope  (0) 2020.11.19