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μ λ€μκ³Ό κ°μ΅λλ€.
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λ₯Ό νλλ‘ κ°μ§κ³ μμ΅λλ€.
ν΄λΉ νλλ μμ±μλ₯Ό ν΅ν΄ μ΄κΈ°νλ₯Ό ν©λλ€.
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)κ°μ²΄λ₯Ό μ΄μ©νλ λ°©λ²μ΄ μμ΅λλ€.
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λ μ€νμμ€ λͺ© νλ μμν¬μ λλ€.
ν μ€νΈλ₯Ό μν΄ κ°μ§ κ°μ²΄λ₯Ό μ½κ² λ§λ€μ΄ μ€ μ μλ νλ μμν¬λΌκ³ μκ°νλ©΄ νΈν©λλ€.
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 |