μΌ | μ | ν | μ | λͺ© | κΈ | ν |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- νν΄νλ¬μ€νκΈ°
- pull model
- μμ°¨μ§ν₯
- λ°μ΄ν° 쿼리
- νν΄νλ¬μ€λ°±μλ
- λΉ μ€μ½ν
- νν λ°±μλ
- νν΄νλ¬μ€
- νν΄νλ¬μ€ λ°±μλ
- μμ± ν¨ν΄
- κΈ°λ₯ ν μ€νΈ
- push model
- νλ‘ν νμ λΉ
- νν νκΈ°
- νν΄νλ¬μ€ νκ³
- νν΄νλ¬μ€ νκΈ°
- fanout on read
- νν
- νν΄ νκΈ°
- νν΄+
- νν΄
- νν΄ νλ¬μ€ νκΈ°
- νΌλ ꡬν
- OOP
- μ±κΈν€ λΉ
- TDD
- λμμΈ ν¨ν΄
- API Aggregation
- fanout on write
- νν΄ λ°±μλ
- Today
- Total
deVlog
[TDD] ν μ€νΈ λλΈ - Mock vs Stub vs Spy λ³Έλ¬Έ
[TDD] ν μ€νΈ λλΈ - Mock vs Stub vs Spy
μλ£¨λ° 2024. 8. 31. 13:06λͺ©μ°¨
π§π€π§ ν μ€νΈ λλΈ
https://martinfowler.com/bliki/TestDouble.html
ν μ€νΈ λλΈμ μννΈμ¨μ΄ ν μ€νΈμμ μ€μ κ°μ²΄λ₯Ό λμ νμ¬ μ¬μ©λλ κ°μ§ κ°μ²΄ λ€λ‘, ν μ€νΈ νκ²½μμ λ€μν λͺ©μ μ μν΄ νμ©λλ€.
λ§ν΄ νμΈλ¬λ μμ κ²μκΈμμ ν μ€νΈ λλΈμ λ€μ― κ°μ§λ‘ λΆλ₯νλ€.
- Dummy : κ°μ²΄λ μ λ¬λμ§λ§ μ€μ λ‘ μ¬μ©λμ§ μλλ€. μΌλ°μ μΌλ‘ νλΌλ―Έν°λ₯Ό μ λ¬νκΈ° μν μ©λλ‘λ§ μ¬μ©λλ€.
- Fake : μ€μ λ‘ λμνλ κ°μ²΄λ₯Ό μλ―Ένλ€. λ³΄ν΅ νλ‘λμ μ νκ²½μ μ ν©νμ§ μμ μ§λ¦κΈΈ μν μ νλ€. (μΈλ©λͺ¨λ¦¬ λ°μ΄ν°λ² μ΄μ€ κ° μ’μ μμμ΄λ€).
- Stub : ν μ€νΈ μ€μ νΈμΆλ κ²½μ°μ λν΄ λ―Έλ¦¬ μ ν΄μ§ κ°μ μλ΅νλ€. λ³΄ν΅ ν μ€νΈλ₯Ό μν΄ λ§λ€μ΄μ§λ©° ν μ€νΈ μ΄μΈμ μ¬μ©λμ§ μλλ€.
- Spy : νΈμΆ λ°©μμ λ°λΌ μΌλΆ μ 보λ₯Ό κΈ°λ‘νλ μ€ν μ΄λΌ ν μ μλ€. μ£Όλ‘ μ΄λ€ λμμ΄ μ΄λ£¨μ΄μ‘λμ§ κ²μ¦νλ μ©λλ‘ μ¬μ©νλ€. μ μ‘λ λ©μμ§ μλ₯Ό κΈ°λ‘νλ μ΄λ©μΌ μλΉμ€κ° ν μμμ΄λ€.
- Mock : νΈμΆνμ λ μ¬μ μ μ μλ λͺ μΈλλ‘μ κ²°κ³Όλ₯Ό λλ €μ£Όλλ‘ λ―Έλ¦¬ νλ‘κ·Έλλ°λμ΄ μλ€. μμμΉ λͺ»ν νΈμΆμ΄ μμ κ²½μ° μμΈλ₯Ό λμ§ μ μμΌλ©°, λͺ¨λ νΈμΆμ΄ μμλ κ²μ΄μλμ§ νμΈν μ μλ€.
μμ μ μλ ν μ€νΈ λλΈ μ€μμ Mock λ§ νμλ₯Ό κ²μ¦νλ€. λ³΄ν΅ λ€λ₯Έ λλΈμ μν κ²μ¦μ μν΄ μ¬μ©νλ€.
π μν κ²μ¦ vs νμ κ²μ¦
μν κ²μ¦κ³Ό νμ κ²μ¦μ μννΈμ¨μ΄ ν μ€νΈμμ μ¬μ©λλ λ κ°μ§ μ£Όμ μ κ·Ό λ°©μμ΄λ©°, ν μ€νΈ λμμ λμμ κ²μ¦νλ λ°©λ²μ μ°¨μ΄λ₯Ό λκ³ μλ€.
μν κ²μ¦ (State Verification)
- μμ€ν μ΄ νΉμ μνμ λλ¬νλμ§λ₯Ό νμΈνλ ν μ€νΈ λ°©μμ΄λ€.
- μ£Όλ‘ μμ€ν μ λ©μλλ κΈ°λ₯μ΄ νΈμΆλ νμ, κ·Έ κ²°κ³Όλ‘ μμ€ν μ μνκ° μμλ λλ‘ λ³νλμ§λ₯Ό κ²μ¬νλ€.
μμ) μν κ³μ’μ λμ μ κΈνλ λ©μλλ₯Ό ν μ€νΈν λ, μ κΈ ν κ³μ’ μκ³ κ° μ¬λ°λ₯΄κ² μ λ°μ΄νΈλμλμ§λ₯Ό νμΈνλ€.
- μν© : μν κ³μ’μ λμ μ κΈνλ κΈ°λ₯μ ν μ€νΈ
- ν μ€νΈ : κ³μ’μ 100,000μμ μ κΈν ν, μκ³ κ° 500,000μμμ 600,000μμΌλ‘ μ¦κ°νλμ§λ₯Ό νμΈνλ€.
- κ²μ¦ : μ κΈ ν κ³μ’ μκ³ κ° 600,000μμ΄ λμλμ§λ₯Ό νμΈνμ¬ μνλ₯Ό κ²μ¦νλ€.
νμ κ²μ¦ (Behavior Verification)
- μμ€ν μ΄ μ¬λ°λ₯Έ μ μ°¨λ λ°©λ²μ λ°λΌ μλνλμ§λ₯Ό νμΈνλ ν μ€νΈ λ°©μμ΄λ€.
- νΉμ μμ μ μννλ λμ μ¬λ°λ₯Έ λ©μλλ μ μ°¨λ₯Ό νΈμΆνλμ§, νΉμ μΈν°νμ΄μ€μ μ¬λ°λ₯΄κ² μνΈμμ© νλμ§λ₯Ό κ²μ¬νλ€.
μμ) μν κ³μ’μ λμ μ κΈνλ λ©μλλ₯Ό ν μ€νΈν λ, μ κΈ κ³Όμ μμ μ¬λ°λ₯Έ λ©μλλ€μ΄ νΈμΆλμλμ§λ₯Ό νμΈνλ€.
- μν©: μν κ³μ’μ λμ μ κΈνλ κΈ°λ₯μ ν μ€νΈ
- ν μ€νΈ: κ³μ’μ 100,000μμ μ κΈνλ λμ, μκ³ μ λ°μ΄νΈ λ©μλμ μ κΈ λ΄μ κΈ°λ‘ λ©μλκ° μ¬λ°λ₯Έ μμλ‘ νΈμΆλμλμ§λ₯Ό νμΈνλ€.
- κ²μ¦: μ κΈ κ³Όμ μμ μκ³ μ λ°μ΄νΈ λ©μλκ° νΈμΆλμκ³ , κ·Έ ν μ κΈ λ΄μ κΈ°λ‘ λ©μλκ° νΈμΆλμλμ§λ₯Ό νμΈνμ¬ νμλ₯Ό κ²μ¦νλ€.
μν κ²μ¦μ μμ€ν μ κ²°κ³Όλ₯Ό μ€μ μ μΌλ‘ νμΈνλ©°, μ΅μ’ μνκ° μ¬λ°λ₯Έμ§μ μ΄μ μ λ§μΆλ€.
νμ κ²μ¦μ μμ€ν μ νλ κ³Όμ μ μ€μ μ μΌλ‘ νμΈνλ©°, μμ€ν μ΄ μ¬λ°λ₯΄κ² νλνλμ§λ₯Ό νκ°νλ€.
λ κ²μ¦ λ°©μμ μλ‘ λ³΄μμ μ΄λ©°, νΉμ μν©μ λ°λΌ νλ λλ λ λ€ μ¬μ©ν μ μλ€.
π₯Έ Mock : κΈ°λν λλ‘ μ νΈμΆμ΄ λλ? - νμ κ²μ¦
Mock μ νΉμ λ©μλ νΈμΆμ΄ μμλλ‘ μ΄λ£¨μ΄μ‘λμ§ νμΈνκΈ° μν λͺ©μ μΌλ‘ μ¬μ©λλ€.
Mockμ νΉμ§
- νΈμΆμ λν κΈ°λλ₯Ό λͺ μΈνκ³ , λ΄μ©μ λ°λΌ λμνλλ‘ νλ‘κ·Έλλ°λ κ°μ²΄μ΄λ€.
- νμ κ²μ¦μ μννλ€.
- λ°νκ°μ΄ μλ ν¨μλ, νΉμ ν¨μ νΈμΆ μ¬λΆλ₯Ό ν μ€νΈν λ μ£Όλ‘ μ¬μ©λλ€.
- @Mock μ΄λ Έν μ΄μ μ ν΅ν΄ μμ±λλ©°, stubbingμ ν΅ν΄ λ°νκ°μ μ€μ ν μ μλ€. stubbingμ νμ§ μμΌλ©΄ κΈ°λ³Έ κ°(μ°Έμ‘°νμ null, κΈ°λ³Ένμ 0)μ λ°ννλ€.
Mock μ ν μ€νΈ μ€μ νΉμ μΈν°νμ΄μ€λ₯Ό ꡬννλ κ°μ²΄λ₯Ό λ체νλ λ° μ¬μ©λλ€. μ¦, κ°μ§ ν μ€νΈ μλ¨μ λ§λ€μ΄ λλ κ²μ΄λ€.
μ΄λ κ² λ체λ Mock κ°μ²΄λ μμ μΈκΈν λλ‘ νΉμ λ©μλκ° νΈμΆλμλμ§, μ΄λ€ μΈμλ‘ νΈμΆλμλμ§ κ²μ¬νλ λ° μ€μ μ λλ€.
π Stub : κΈ°λν κ°μ΄ μ λ°νλλ? - μν κ²μ¦
Stub κ°μ²΄λ νΉμ ν¨μ νΈμΆ μ μμλ κ°μ λ°ννλλ‘ μ€μ λ κ°μ²΄μ΄λ€.
Stubμ νΉμ§
- μΈμ€ν΄μ€ννμ¬ κ΅¬νν κ°μ§ κ°μ²΄(Dummy, κΈ°λ₯ ꡬνμ΄ μμ)λ₯Ό μ΄μ©ν΄ μ€μ λ‘ λμνλ κ²μ²λΌ 보μ΄κ² λ§λλ κ°μ²΄μ΄λ€.
- μΈν°νμ΄μ€ λλ κΈ°λ³Έ ν΄λμ€λ₯Ό μ΅μνμΌλ‘ ꡬννλ€.
- μν κ²μ¦μ μν΄ μ¬μ©λλ€. μ¦, ν¨μ νΈμΆ ν κ°μ²΄μ μνκ° μ¬λ°λ₯Έμ§ νμΈνλ€.
- ν μ€νΈ μμ νλ‘κ·Έλλ°λ κ² μΈμλ μλ΅νμ§ μλλ€.
- νλ ₯ κ°μ²΄μ νΉμ λΆλΆμ΄ ν μ€νΈκ° μ΄λ €μ΄ κ²½μ°, stubμ μ¬μ©νμ¬ μμνκ² ν μ€νΈν μ μλ€.
- ν μ€νΈ μ€μ μ¬μ©λλ νλμ½λ© λ κ° λλ μλ΅μ μ 곡νλ λ° μ¬μ©λλ€.
Stubμ νΉμ κ°μ²΄μμ νΉμ ν¨μλ₯Ό νΈμΆν λ, νΉμ ν κ°μ΄ λ°νλκΈ°λ₯Ό κΈ°λνλ©° λλ―Έ λ°μ΄ν°λ₯Ό μ§μ ν λ μ¬μ©νλ€.
볡μ‘ν λ‘μ§μ΄λ μΈλΆ μμ€ν κ³Όμ μνΈμμ©μ λ¨μννκ³ , ν μ€νΈλ₯Ό λ μμΈ‘ κ°λ₯νκ² λ§λλ λ° μ€μ μ λλ€.
π Spy : μμν λμκ³Ό μνλ₯Ό κ°μ
Spyλ νΉμ ν¨μλ§ μ€μ ν¨μλ₯Ό νΈμΆνκ² νκ³ μΆμ λ, κΈ°μ‘΄μ κ°μ²΄λ ν¨μλ₯Ό κ°μνλ λ°μ μ¬μ©λλ€. μ΄λ ν¨μ νΈμΆ, μ λ¬λ μΈμ, λ°ν κ° λ±μ κΈ°λ‘νμ§λ§, μ€μ λ‘μ§μ λμμ λ³κ²½νμ§λ μλλ€.
Spyμ νΉμ§
- νΉμ ν¨μμ νΈμΆ νμ, μ λ¬λ μΈμ, λ°ν κ° λ±μ κΈ°λ‘νλ€.
- μ€μ κ°μ²΄μ λμμ μ μ§νλ©΄μ νΉμ λΆλΆλ§ κ°μνκ±°λ μ‘°μνκ³ μΆμ λ μ¬μ©νλ€.
λΆλΆμ μΈ μ€ν°λΉμ ν΅ν΄ μ μ°νκ² ν μ€νΈλ₯Ό μ§νν μ μλ€. - @Spy μ΄λ Έν μ΄μ μ μ¬μ©νλ©°, stubbingμ νμ§ μμΌλ©΄ μ€μ λ‘μ§μ΄ μνλλ€. stubbing μ νλ©΄ μ€μ λ κ°μ λ°ννλ€.
βμ΄λ μν©μ μ΄λ ν ν μ€νΈ λλΈμ μ¬μ©ν΄μΌ ν κΉ
Mockμ μ¬μ©ν΄μΌ νλ κ²½μ°
- μ 체 κ°μ²΄λ₯Ό κ°μ§λ‘ λ체νκ³ μΆμ λ
ν μ€νΈ νκ²½μμ 볡μ‘ν μμ‘΄μ±μ μ κ±°νκ³ , ν μ€νΈνκ³ μ νλ λΆλΆμλ§ μ§μ€νλ€. μλ₯Ό λ€μ΄, μΈλΆ API νΈμΆμ μμ ν Mockingνμ¬ ν μ€νΈν λ μ¬μ©νλ€. - νμ κ²μ¦(Behavior Verification)μ μ§μ€νκ³ μΆμ λ
νΉμ λ©μλκ° νΈμΆλμλμ§, νΈμΆλ νμ, νΈμΆλ μΈμ λ±μ κ²μ¦ν λ Mockμ μ¬μ©νλ€.
μ΄λ Mockμ μ€μ λμμ μννμ§ μμΌλ―λ‘, μΈλΆ μμ€ν κ³Όμ μνΈμμ©μ ν μ€νΈν λ μμ νκ² μ¬μ©ν μ μλ€. - ν
μ€νΈκ° μ€μ λμκ³Ό 무κ΄ν λ
ν μ€νΈκ° νΉμ λ‘μ§μ μ€ν μ¬λΆλ λ°©μμλ§ κ΄μ¬μ΄ μκ³ , κ·Έ λ‘μ§μ μ€μ κ²°κ³Όλ μνλ μ€μνμ§ μμ λ μ¬μ©νλ€.
μλ₯Ό λ€μ΄, μ΄λ²€νΈ νΈλ€λ¬κ° μ¬λ°λ₯΄κ² λ±λ‘λκ³ νΈμΆλλμ§ νμΈνκ³ , κ·Έ κ²°κ³Όλ μ€μνμ§ μμ κ²½μ°μ μ ν©νλ€.
Stubμ μ¬μ©ν΄μΌ νλ κ²½μ°
- ν
μ€νΈμ μ
λ ₯μ μ§μ€ν λ
μ λ ₯ κ°μ λ°λΌ 리ν΄νλ κ²°κ΄ κ°μ λΉκ΅νκ±°λ, νΉμ μ λ ₯ κ°μ λν μμΈ λ°μ μ¬λΆλ₯Ό νμΈνλ€. μλ₯Ό λ€μ΄, λ©μλκ° μ£Όμ΄μ§ μ λ ₯μ λν΄ μμλ κ²°κ³Όλ₯Ό λ°ννλμ§ κ²μ¦ν λ μ¬μ©νλ€. - μ
λ ₯μ λ°λΌ μμΈκ° λ°μνλμ§ νμΈν λ
νΉμ μ λ ₯ κ°μ΄ μ£Όμ΄μ‘μ λ, λ©μλκ° μ¬λ°λ₯΄κ² μμΈλ₯Ό λ°μμν€λμ§ νμΈνλ€. μλ₯Ό λ€μ΄, μλͺ»λ μ λ ₯μ λν μ μ ν μμΈ μ²λ¦¬λ₯Ό ν μ€νΈν λ μ¬μ©νλ€.
Spyλ₯Ό μ¬μ©ν΄μΌ νλ κ²½μ°
- λΆλΆμ μΌλ‘ μ€μ κ°μ²΄μ λμμ μ μ§νκ³ μΆμ λ
μ€μ κ°μ²΄λ₯Ό μμ±ν ν, μΌλΆ λ©μλλ§ κ°μνκ±°λ μ€ν°λΉ(stubbing) ν μ μλ€. 볡μ‘ν ν΄λμ€μμ νΉμ λ©μλμ νΈμΆ νμλ μΈμλ₯Ό νμΈνλ©΄μλ λλ¨Έμ§ λ©μλλ€μ μλμ λμμ μ μ§νκ³ μΆμ λ μ¬μ©νλ€. - μ€μ λ‘μ§μ ν
μ€νΈνλ©΄μ νΉμ λΆλΆλ§ μ‘°μνκ³ μΆμ λ
μ 체 λ©μλ νΈμΆ νλ¦μ μ μ§νλ©΄μ νΉμ λ©μλμ λ°νκ°λ§ λ³κ²½ν΄ ν μ€νΈλ₯Ό μ§ννλ€. 볡μ‘ν κ³μ°μ μννλ λ©μλμ μΌλΆ κ²°κ³Όλ§ μ‘°μνκ³ , λλ¨Έμ§ νλ¦μ κ·Έλλ‘ μ μ§νκ³ μΆμ λ μ μ©νλ€.
spy μ¬μ© μμ μ½λ
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int multiply(int a, int b) {
return a * b;
}
public int subtract(int a, int b) {
return a - b;
}
}
public class SpyCalculator extends Calculator {
private final List<String> methodCalls = new ArrayList<>();
@Override
public int add(int a, int b) {
methodCalls.add("add(" + a + ", " + b + ")");
return super.add(a, b); // μ€μ λ©μλ νΈμΆ
}
@Override
public int multiply(int a, int b) {
methodCalls.add("multiply(" + a + ", " + b + ")");
return 100; // μ€ν°λΉ μ²λ¦¬λ κ°
}
// subtract μ κ°μX, μ€ν°λΉX
// λ©μλ νΈμΆ λ΄μμ νμΈνλ λ©μλ
public boolean wasMethodCalled(String methodCall) {
return methodCalls.contains(methodCall);
}
}
- SpyCalculator ν΄λμ€λ Calculator ν΄λμ€λ₯Ό νμ₯ν κ²μΌλ‘, λ©μλ νΈμΆμ κ°μνκ³ νΉμ λ©μλμ λν΄ μ€ν°λΉμ μ μ©νλ€.
- add λ©μλλ μ€μ κ³μ°μ μννκ³ , νΈμΆ λ΄μμ κΈ°λ‘νλ€.
- multiply λ©μλλ νΈμΆ λ΄μμ κΈ°λ‘ν ν, νμ 100μ λ°ννλ μ€ν°λΉ μ²λ¦¬λ λ©μλμ΄λ€.
- addμ multiply λ©μλκ° νΈμΆλ λ νΈμΆ λ΄μμ methodCalls 리μ€νΈμ κΈ°λ‘νλ€. -> wasMethodCalled(String methodCall) λ©μλλ₯Ό μ¬μ©νμ¬ νΉμ λ©μλ νΈμΆ λ΄μμ΄ κΈ°λ‘λμλμ§ νμΈν μ μλ€.
public class SpyCalculatorTest {
@Test
public void testOriginalCalculator() {
// μλμ Calculator κ°μ²΄ μμ±
Calculator calculator = new Calculator();
// μλ Calculatorμ add λ©μλλ μλ λμμ μν
int originalAddResult = calculator.add(2, 3);
assertEquals(5, originalAddResult);
// μλ Calculatorμ multiply λ©μλλ μλ λμμ μν
int originalMultiplyResult = calculator.multiply(2, 3);
assertEquals(6, originalMultiplyResult);
}
@Test
public void testSpyCalculatorWithStubbingAndVerification() {
// SpyCalculator κ°μ²΄ μμ±
SpyCalculator spyCalculator = new SpyCalculator();
// multiply λ©μλλ μ€ν°λΉλ κ°(100)μ λ°ν
int multiplyResult = spyCalculator.multiply(2, 3);
assertEquals(100, multiplyResult);
// add λ©μλλ μ€μ λμμ μν
int addResult = spyCalculator.add(2, 3);
assertEquals(5, addResult);
// subtract λ©μλλ μ€μ λμμ μν
int subtractResult = spyCalculator.subtract(5, 3);
assertEquals(2, subtractResult);
// λ©μλ νΈμΆ κ°μ
assertTrue(spyCalculator.wasMethodCalled("multiply(2, 3)")); // multiply λ©μλκ° νΈμΆλμλμ§ νμΈ
assertTrue(spyCalculator.wasMethodCalled("add(2, 3)")); // add λ©μλκ° νΈμΆλμλμ§ νμΈ
}
// Mockito μ¬μ©
@Test
public void testCalculatorWithSpy() {
// μ€μ Calculator κ°μ²΄ μμ±
Calculator realCalculator = new Calculator();
// Calculatorμ spy κ°μ²΄ μμ±
Calculator spyCalculator = spy(realCalculator);
// multiply λ©μλλ₯Ό μ€ν°λΉ μ²λ¦¬νμ¬ νμ 100μ λ°ννλλ‘ μ€μ
doReturn(100).when(spyCalculator).multiply(2, 3);
// ν
μ€νΈ: multiply λ©μλλ μ€ν°λΉλ κ°(100)μ λ°ν
int multiplyResult = spyCalculator.multiply(2, 3);
assertEquals(100, multiplyResult);
// ν
μ€νΈ: add λ©μλλ μ€μ λμμ μν
int addResult = spyCalculator.add(2, 3);
assertEquals(5, addResult);
// ν
μ€νΈ: subtract λ©μλλ μ€μ λμμ μν
int subtractResult = spyCalculator.subtract(5, 3);
assertEquals(2, subtractResult);
// λ©μλ νΈμΆ κ²μ¦
verify(spyCalculator).multiply(2, 3); // multiply(2, 3) νΈμΆ κ²μ¦
verify(spyCalculator).add(2, 3); // add(2, 3) νΈμΆ κ²μ¦
verify(spyCalculator).subtract(5, 3); // subtract(5, 3) νΈμΆ κ²μ¦
}
}
μ°Έκ³ λ¬Έν
'π Test Driven Development' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[TDD] ν μ€νΈ μ½λμ μ μ§λ³΄μ (0) | 2024.09.01 |
---|---|
[TDD] ν μ€νΈ λ²μμ μ’ λ₯ (0) | 2024.09.01 |