π Chapter 3: λꡬ μκ°
π κ°λ΅ν JUnit 4 μκ°β
- μλ° ν μ€νΈ νλ μμν¬λ‘ JUnit 4λ₯Ό μ¬μ©νλ€.
- JUnitμ 리νλ μ μ ν΅ν΄ ν΄λμ€ κ΅¬μ‘°λ₯Ό νμ ν ν ν΄λΉ ν΄λμ€ λ΄μμ ν μ€νΈλ₯Ό λνλ΄λ κ²μ λͺ¨λ μ€ννλ€.
- μ΄λ₯Ό ν
λ©΄, λ€μμ
Entry
κ°μ²΄μ 컬λ μ μ κ΄λ¦¬νλCatalog
ν΄λμ€λ₯Ό μννλ ν μ€νΈλ€.
public class CatalogTest {
private final Catalog catalog = new Catalog();
@Test public void containsAnAddedEntry() {
Entry entry = new Entry("fish", "chips");
catalog.add(entry);
assertTrue(catalog.contains(entry));
}
@Test public void indexesEntriesByName() {
Entry entry = new Entry("fish", "chips");
catalog.add(entry);
assertEquals(entry, catalog.entryFor("fish"));
assertNull(catalog.entryFor("missing name"));
}
}
π ν μ€νΈ μΌμ΄μ€β
- JUnitμμλ
@Test
λΌλ μ λ Έν μ΄μ μ΄ μ§μ λ λ©μλλ λͺ¨λ ν μ€νΈ μΌμ΄μ€λ‘ μ·¨κΈνλ€. ν μ€νΈ λ©μλλ κ°μ λ°ννκ±°λ 맀κ°λ³μλ₯Ό λ°μμλ μ λλ€. μ μμ μ κ²½μ°CatalogTest
ν΄λμ€μλcontainsAnAddedEntry
,indexesEntriesByName
μ΄λΌλ ν μ€νΈ λ κ°κ° μ μλΌ μλ€. - JUnitμμλ ν μ€νΈλ₯Ό μ€ννκΈ° μν΄ ν μ€νΈ ν΄λμ€μ μ μΈμ€ν΄μ€λ₯Ό μμ±ν ν μ μ ν ν μ€νΈ λ©μλλ₯Ό νΈμΆνλ€.
π λ¨μ β
- JUnit ν μ€νΈμμλ ν μ€νΈ λμ κ°μ²΄λ₯Ό νΈμΆνκ³ κ·Έ κ²°κ³Όλ₯Ό λ¨μ (assertion)νλλ°, λ³΄ν΅ JUnitμ μ μλΌ μλ λ¨μ λ©μλλ₯Ό μ¬μ©νλ©°, μ΄λ¬ν λ©μλλ λ¨μ μ΄ μ€ν¨ν λ μ μ©ν μ€λ₯ λ©μμ§λ₯Ό λ§λ€μ΄λΈλ€.
- μλ₯Ό λ€μ΄,
CatalogTest
μμλ JUnitμ μΈ κ°μ§ λ¨μ λ© μλλ₯Ό μ¬μ©νλλ°,assertTrue
λ ννμμ΄ μ°Έμμ λ¨μ νκ³assertNull
μ κ°μ²΄ μ°Έμ‘°κ°null
μμ λ¨μ νλ©°,assertEquals
λ λ κ°μ΄ λμΌν¨μ λ¨μ νλ€. λ§μ½ μ€ν¨νλ©΄ μμ κ°κ³Ό μ€μ κ°μ λΉκ΅ν λ΄μ©μ 보μ¬μ€λ€.
π μμΈ μμνκΈ°β
@Test
μ λ Έν μ΄μ μ μ νμ μΈ λ§€κ°λ³μλ‘expected
λΌλ κ²μ μ§μνλ€. μ΄ λ§€κ°λ³μλ ν μ€νΈ μΌμ΄μ€μμ μμΈλ₯Ό λμ§ κ²μΌλ‘ μ μΈνλ€. ν μ€νΈμμ μμΈλ₯Ό λμ§μ§ μκ±°λ λ€λ₯Έ μ νμ μμΈλ₯Ό λμ§λ©΄ ν μ€νΈκ° μ€ν¨νλ€.- μλ₯Ό λ€μ΄, λ€μ ν
μ€νΈμμλ
Catalog
μμ λ νλͺ©μ΄ κ°μ μ΄λ¦μΌλ‘ μΆκ°λ κ²½μ°IllegalArgumentException
μ λμ§λμ§ κ²μ¬νλ€.
@Test(expected=IllegalArgumentException)
public void cannotAddTwoEntriesWithTheSameName() {
catalog.add(new Entry("fish", "chips"));
catalog.add(new Entry("fish", "peas"));
}
π ν μ€νΈ ν½μ€μ²β
- ν μ€νΈ ν½μ€μ²(test fixture)λ ν μ€νΈλ₯Ό μμν λ μ‘΄μ¬νλ κ³ μ λ μνλ₯Ό μλ―Ένλ€. ν μ€νΈ ν½μ€μ²λ ν μ€νΈκ° λ°λ³΅ κ°λ₯ν¨μ 보μ₯νλ€. μ¦, ν μ€νΈκ° μ€νλ λλ§λ€ ν΄λΉ ν μ€νΈλ λμΌν μνλ‘ μμνλ―λ‘ λμΌν κ²°κ³Όλ₯Ό λΌ κ²μ΄λ€.
- ν½μ€μ²λ ν μ€νΈκ° μ€νλκΈ° μ μ μ€λΉν΄μ ν μ€νΈ μ€νμ΄ μλ£λ νμ μ 리ν μ μλ€.
- JUnit ν
μ€νΈμμ μ¬μ©λλ ν½μ€μ²λ ν΄λΉ ν
μ€νΈλ₯Ό μ μν ν΄λμ€μμ κ΄λ¦¬νκ³ κ°μ²΄μ νλμ μ μ₯λλ€. κ°μ ν΄λμ€μ μ μλ ν
μ€νΈλ λͺ¨λ λμΌν ν½μ€μ²λ₯Ό κ°μ§κ³ μμνλ©°, μ€νλ λ ν΄λΉ ν½μ€μ²λ₯Ό λ³κ²½ν΄λ λλ€.
CatalogTest
μμ ν½μ€μ²λcatalog
νλμ μ μ₯λ λΉCatalog
κ°μ²΄λ€. - JUnitμμλ μ λ
Έν
μ΄μ
μΌλ‘ ν½μ€μ²λ₯Ό μ€λΉνκ±°λ μ 리νλ λ©μλλ₯Ό ꡬλΆν μλ μλ€. ν
μ€νΈλ₯Ό μ€ννκΈ° μ μ
@Before
μ λ Έν μ΄μ μ΄ μ§μ λ λ©μλλ₯Ό λͺ¨λ μ€ννκ³ , ν½μ€μ²λ₯Ό μ 리νκΈ° μν΄ ν μ€νΈκ° μ€νλ ν@After
λΌλ μ λ Έν μ΄μ μ΄ μ§μ λ λ©μλλ₯Ό μ€ννλ€. - λ§μ JUnit ν μ€νΈμμ λͺ μμ μΌλ‘ ν½μ€μ²λ₯Ό μ 리νμ§ μμλ λλλ°, ν½μ€μ²λ₯Ό μ€λΉν λ JVM κ°λΉμ§ 컬λ μ μΌλ‘ μμ±λ κ°μ²΄λ₯Ό μκ±°νλ κ²λ§μΌλ‘λ μΆ©λΆνκΈ° λλ¬Έμ΄λ€.
- λ€μ μμ²λΌ ν
μ€νΈμμ λͺ¨λ λμΌν νλͺ©μΌλ‘
catalog
λ₯Ό μ΄κΈ°νν μ μλ€.
public class CatalogTest {
final Catalog catalog = new Catalog();
final Entry entry = new Entry("fish", "chips");
@Before public void fillTheCatalog() {
catalog.add(entry);
}
// ...
}
π ν μ€νΈ λ¬λβ
- JUnitμ΄ ν΄λμ€λ₯Ό λμμΌλ‘ 리νλ μ
μ μνν΄ ν
μ€νΈλ₯Ό μ°Ύμ ν΄λΉ ν
μ€νΈλ₯Ό μ«ννλ λ°©μμ ν
μ€νΈ λ¬λμμ μ μ΄νλ€. ν΄λμ€μ μ¬μ©λλ λ¬λλ
@RunWith
μ λ Έν μ΄μ μΌλ‘ μ€μ ν μ μλ€.
π νν¬λ μ€νΈ 맀μ²μ assertThat()β
- νν¬λ μ€νΈλ λ§€μΉ μ‘°κ±΄μ μ μΈμ μΌλ‘ μμ±νλ νλ μμν¬λ€. νν¬λ μ€νΈ μ체λ ν μ€νΈ νλ μμν¬κ° μλμ§λ§ JUnitμ΄λ jMockμ λΉλ‘―ν΄ μλ리컀 κ°μ μ¬λ¬ ν μ€νΈ νλ μμν¬μμ μ°μΈλ€.
- νν¬λ μ€νΈμ 맀μ²λ νΉμ κ°μ²΄κ° μ΄λ€ 쑰건과 μΌμΉνλμ§ μλ €μ£Όλ©°, ν΄λΉ 쑰건μ΄λ κ°μ²΄κ° μ΄λ€ 쑰건과 μΌμΉνμ§ μλ μ΄μ μ κΈ°μ ν μ μλ€.
- μ΄λ₯Όν λ©΄, λ€μ μ½λλ νΉμ λΆλ¬Έμμ΄(substring)μ λ΄μ λ¬Έμμ΄κ³Ό 맀μΉλλ 맀μ²λ₯Ό μμ±νκ³ ν΄λΉ 맀μ²λ₯Ό μ¬μ©ν΄ λ¨μ μ μννλ€.
String s = "yes we have no bananas today";
Matcher<String> containsBananas = new StringContains("bananas");
Matcher<String> containsMangoes = new StringContains("mangoes");
assertTrue(containsBananas.matches(s));
assertFalse(containsMangoes.matches(s));
- λκ° λ§€μ²λ μ§μ μ μΌλ‘ μΈμ€ν΄μ€νλμ§ μλλ€. λμ νν¬λ μ€νΈλ 맀μ²λ₯Ό μμ±νλ μ½λμ κ°λ μ±μ λμ΄κ³ μ λͺ¨λ 맀μ²μ λν μ μ ν©ν°λ¦¬ λ©μλλ₯Ό μ 곡νλ€.
assertTrue(containsString("bananas").matches(s));
assertFalse(containsString("mangoes").matches(s));
- νμ§λ§ μ€μ λ‘λ 맀μ²λ₯Ό JUnitμ
assertThat()
κ³Ό μ‘°ν©ν΄ μ¬μ©νλ€.assertThat()
μ 맀μ²μ μκΈ°μμ μ μΈ νΉμ±μ νμ©ν΄ λ¨μ μ΄ μ€ν¨ν κ²½μ° λκ° μλͺ»λλμ§ λΆλͺ νκ² λλ¬λΈλ€.
assertThat(s, containsString("bananas"));
assertThat(s, not(containsString("mangoes")));
- λ λ²μ§Έ λ¨μ μ νν¬λ μ€νΈμ κ°μ₯ μ μ©ν κΈ°λ₯μΈλ° λ°λ‘ κΈ°μ‘΄ 맀μ²λ₯Ό μ‘°ν©ν΄ μλ‘μ΄ μ‘°κ±΄μ μ μν λ κΈ°λ₯μ΄λ€.
not()
λ©μλλ₯Ό μ λ¬λ 맀μ²μ μλ―Έμ λ°λλλ 맀μ²λ₯Ό μμ±νλ ν©ν°λ¦¬ ν¨μλ€. 맀μ²λ₯Ό μ‘°ν©νλλΌλ μ½λμ μ€ν¨ λ©μμ§ λͺ¨λ μκΈ°μμ μ μΈ νΉμ±μ λ κ²λ μ€κ³λΌ μλ€. - μ½λλ₯Ό μμ±ν΄ λͺ
μμ μΌλ‘ 쑰건μ κ²μ¬νκ±°λ νλΆν μ 보λ₯Ό λλ¬λ΄λ μ€λ₯ λ©μμ§λ₯Ό λ§λ€μ΄ λ΄λ κ² μλλΌ
assertThat()
μ λ§€μ² ννμμ μ λ¬νκ³assertThat()
μ΄ κ·Έ μΌμ μμμ μ²λ¦¬νκ² ν μ μλ€.
π jMock2: λͺ© κ°μ²΄β
- jMock2λ JUnitμ λΆμ¬μ λͺ© κ°μ²΄λ₯Ό νμ©ν ν μ€νΈ λ°©μμ μ§μνλ€. jMockμ λͺ© κ°μ²΄λ₯Ό λμ μΌλ‘ μμ±νλ―λ‘ λͺ©μ μμ±νλ €λ νμ μ ꡬν체λ₯Ό μ§μ μμ±νμ§ μμλ λλ€. λ jMockμ ν μ€νΈ λμ κ°μ²΄ κ° κ·Έκ²κ³Ό μνΈ μμ© μ€μΈ λͺ© κ°μ²΄λ₯Ό μ΄λ»κ² νΈμΆνκ³ λͺ© κ°μ²΄κ° κ±°κΈ°μ λ°μν΄ μ΄λ»κ² λμν΄μΌ ν μ§λ₯Ό μ§μ νλ κ³ μμ€ APIλ₯Ό μ 곡νλ€.
- jMock APIμ ν΅μ¬ κ°λ μ λͺ¨μ‘° κ°μ²΄μ λͺ© κ°μ²΄, μμ ꡬ문μ΄λ€. λͺ¨μ‘° κ°μ²΄λ ν μ€νΈ λμ κ°μ²΄μ μ½ν μ€νΈ, μ¦ κ·Έκ²κ³Ό μ΄μνλ κ°μ²΄λ₯Ό νννλ€. λͺ© κ°μ²΄λ ν μ€νΈκ° μ€νλλ κ³Όμ μμ ν μ€νΈ λμ κ°μ²΄μ μ€μ μ΄μμ λμ νλ€. μμ ꡬ문μ ν μ€νΈ κ³Όμ μμ ν μ€νΈ λμ κ°μ²΄κ° κ·Έκ²μ μ΄μμ μ΄λ»κ² νΈμΆν΄μΌ νλμ§ κΈ°μ νλ€.
- λ€μ μμ λ
AuctionMessageTranslator
κ° μ λ¬λ λ©μμ§ ν μ€νΈλ₯Ό ꡬ문 λΆμ(parse)ν΄μauctionClosed()
μ΄λ²€νΈλ₯Ό μμ±ν κ²μΌλ‘ λ¨μ νλ€.
@RunWith(JMock.class)
public class AuctionMessageTranslatorTest {
private final Mockery context = new JUnit4Mockery();
private final AuctionEventListener listener = context.mock(AuctionEventListener.class);
private final AuctionMessageTranslator translator = new AuctionMessageTranslator(listener);
@Test public void
notifiesAuctionClosedWhenCloseMessageReceived() {
Message message = new Message();
message.setBody("SOLVersion: 1.1; Event: CLOSE;");
context.checking(new Expectations() {{
// λ¨μΌ μμ ꡬ문
// auctionClosed λ©μλκ° μ νν ν λ² νΈμΆλ κ²μΌλ‘ μμ
oneOf(listener).auctionClosed();
}});
translator.processMessage(UNUSED_CHAT, message);
}
}
π μμ ꡬ문β
- jMockμ μμ ꡬ문 APIλ ννλ ₯μ΄ λ§€μ° λ°μ΄λλ€.
- μμ ꡬ문 λΈλ‘μ ν΄λΉ μμΈ λΈλ‘μ λλ¬μΌ ν μ€νΈ μ½λμ ꡬλ³ν¨μΌλ‘μ¨ μ΄μ κ°μ²΄κ° μ΄λ»κ² νΈμΆλλμ§ κΈ°μ νλ μ½λμ μ€μ λ‘ κ°μ²΄λ₯Ό νΈμΆνκ³ κ²°κ³Όλ₯Ό κ²μ¬νλ μ½λλ₯Ό λΆλͺ νκ² κ΅¬λΆνλ λ° λͺ©μ μ΄ μλ€.