๐Ÿ“ƒ ํ† ๋น„ ์Šคํ”„๋ง 2์žฅ ์ •๋ฆฌ

10 minute read

  • main()๋กœ ์ž‘์„ฑ๋œ ํ…Œ์ŠคํŠธ
public class UserDaoTest {
  public static void main(String[] args) throws SQLExption {
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
    
      UserDao dao = context.getBean("UserDao", UserDao.class);
  
      User user = new User();

      user.setId("user");
      user.setName("๋ฐฑ๊ธฐ์„ ");
      user.setPassword("married");

      dao.add(user);

      System.out.println(user.getId() + "๋“ฑ๋ก ์„ฑ๊ณต");

      User user2 = dao.get(user.getId());
      Sysyem.out.println(user2.getName());
      System.out.println(user2.getPassword);

      System.out.println(user2.getId() + "์กฐํšŒ ์„ฑ๊ณต")
  } 
}

์œ„ ์ฝ”๋“œ์—์„œ๋Š” main() ๋ฉ”์†Œ๋“œ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ๊ณผ ํ…Œ์ŠคํŠธ ๋Œ€์ƒ์ธ UserDao๋ฅผ ์ง์ ‘ ํ˜น์ถœํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์ ์ด ํŠน์ง•์ด๋‹ค.

๐Ÿ–ฅ ์›น์„ ํ†ตํ•œ DAO ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•์˜ ๋ฌธ์ œ์ 

์„œ๋น„์Šค ํด๋ž˜์Šค, ์ปจํŠธ๋กค๋Ÿฌ, JSP ๋ทฐ ๋“ฑ ๋ชจ๋“  ๋ ˆ์ด์–ด์˜ ๊ธฐ๋Šฅ์„ ๋‹ค ๋งŒ๋“ค๊ณ  ๋‚˜์„œ์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์ด ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋‹ค. ๋”ฐ๋ผ์„œ ์ž‘์€ ๋‹จ์œ„๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Œ

์ด๋ ‡๋“ฏ ์ž‘์€ ๋‹จ์œ„๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด ๋‹จ์œ„ํ…Œ์ŠคํŠธ(Unit Test)๋ผ๊ณ  ํ•จ. ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹จ์œ„๋Š” ์ž‘์„์ˆ˜๋ก ์ ์Œ

๐Ÿ–Š UserDaoTest์˜ ๋ฌธ์ œ์ 

  • ์ˆ˜๋™ ํ™•์ธ ์ž‘์—…์˜ ๋ฒˆ๊ฑฐ๋กœ์›€
    • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ–ˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ set๊ณผ get์˜ ๊ฒฐ๊ณผ๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•ด์•ผํ•จ.
    • ๊ฒ€์ฆํ•ด์•ผ ํ•˜๋Š” ์–‘์ด ๋งŽ์•„์ง€๋ฉด ๋ฒˆ๊ฑฐ๋กœ์›Œ์งˆ์ˆ˜ ๋ฐ–์—ฅ ์—†์Œ
  • ์‹คํ–‰ ์ž‘์—…์˜ ๋ฒˆ๊ฑฐ๋กœ์›€
    • ๋งŒ์•ฝ์— ์‹คํ–‰ํ•  main()์ด ์ˆ˜๋ฐฑ๊ฐœ๋ผ๋ฉด ๋‹น์—ฐํžˆ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ํฐ ๋ถ€๋‹ด์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋งŒ์•ฝ์— ์ „์ฒด ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ํ…Œ์ŠคํŠธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ •๋ฆฌํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ œ๋ฒ• ํฐ ์ž‘์—…์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ main() ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋ณด๋‹ค ์ข€ ๋” ํŽธ๋ฆฌํ•˜๊ณ  ์ฒด๊ณ„์ ์œผ๋กœ ์‹คํ–‰ํ•˜๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์ ˆ์‹คํžˆ ํ•„์š”ํ•˜๋‹ค.

๐Ÿ” UserDaoTest ๊ฐœ์„ 

ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ์˜ ์ž๋™ํ™”

๋ชจ๋“  ํ…Œ์ŠคํŠธ์˜ ๊ฒฐ๊ณผ๋Š” ์„ฑ๊ณต๊ณผ ์‹คํŒจ์ด๋ฉฐ ์‹คํŒจ๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์ง„ํ–‰ํ•˜๋Š” ๋™์•ˆ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ์‹คํŒจํ•˜๋Š” ๊ฒƒ๊ณผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง„ ์•Š์•˜์ง€๋งŒ, ๊ธฐ๋Œ€ํ•œ ๊ฒƒ๊ณผ ๋‹ค๋ฅด๊ฒŒ ๋‚˜์˜ค๋Š” ๊ฒฝ์šฐ 2๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ํ…Œ์ŠคํŠธ ๊ฒ€์ฆ์˜ ์ž๋™ํ™”๋ฅผ ์–ด๋А ์ •๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user2.getId() + " ์กฐํšŒ ์„ฑ๊ณต");

โ†“

if (!user.getName().equal(user2.getName())) {
  System.out.println("ํ…Œ์ŠคํŠธ ์‹คํŒจ (name)");
} else if (!user.getPassword().equal(user2.getName())) {
  System.out.println("ํ…Œ์ŠคํŠธ ์‹คํŒจ (Password)");
} else {
  System.out.println("์กฐํšŒ ํ…Œ์ŠคํŠธ ์„ฑ๊ณต")
}

โš–๏ธ ํ…Œ์ŠคํŠธ์˜ ํšจ์œจ์ ์ธ ์ˆ˜ํ–‰๊ณผ ๊ฒฐ๊ณผ ๊ด€๋ฆฌ

์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ ๋งŒ์œผ๋กœ๋„ ์ž‘์—…์„ ์ƒ๋‹น๋ถ€๋ถ„ ํšจ์œจ์ ์œผ๋กœ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ด๋Ÿฌํ•œ ๊ณผ์ •์œผ๋กœ ์ธํ•ด ๋ฒˆ๊ฑฐ๋กœ์šด ์ผ์ด ์‚ฌ๋ผ์ง„ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด๋‹น ๋ถ€๋ถ„์„ ์ข€ ๋” ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด Junit(Framework)์ด๋ผ๋Š” ํ…Œ์ŠคํŠธ ์ง€์› ๋„๊ตฌ๊ฐ€ ์žˆ๋‹ค.

Junit์€ ํ”„๋ ˆ์ž„์›Œํฌ์ด๊ธฐ ๋•Œ๋ฌธ์— main() ๋ฉ”์†Œ๋“œ๋„ ํ•„์š”์—†๊ณ  ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์‹คํ–‰์‹œํ‚ค๋Š” ์ฝ”๋“œ๋„ ํ•„์š”์—†๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ์กด์˜ main ๋ฉ”์†Œ๋“œ๋Š” Junit์— ์ ์šฉํ•˜๊ธฐ ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๊ฐ€์žฅ ๋จผ์ € ํ•  ์ผ์€ main() ๋ฉ”์†Œ๋“œ์— ์žˆ๋˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ผ๋ฐ˜ ๋ฉ”์†Œ๋“œ๋กœ ์˜ฎ๊ฒจ์•ผํ•œ๋‹ค. ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ค ๋ฉ”์†Œ๋“œ๋Š” Junit ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์š”๊ตฌํ•˜๋Š” 2๊ฐ€์ง€ ์กฐ๊ฑด์„ ๋”ฐ๋ผ์•ผ ํ•œ๋‹ค.

  1. ๋ฉ”์†Œ๋“œ๊ฐ€ public์œผ๋กœ ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค.
  2. ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ๋ฉ”์†Œ๋“œ์— @Test๋ผ๋Š” ์• ๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค.

junit ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๋™์ž‘ํ•˜๋„๋ก ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ๊ตฌ์„ฑํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

import org.junit.Test;
// ...
public class UserDaoTest {
  
  @Test // โ†’ junit์—๊ฒŒ ํ…Œ์ŠคํŠธ์šฉ ๋ฉ”์†Œ๋“œ์ž„์„ ์•Œ๋ ค์ค€๋‹ค. 
  public void addAndGet() throws SQLException { // junit ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋Š” ๋ฐ˜๋“œ์‹œ public์œผ๋กœ ์„ ์–ธ๋˜์–ด์•ผ ํ•œ๋‹ค.
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao dao = context.getBean("userDao", UserDao.class);
  }
}

์ด์ œ ์•„๊นŒ ์ž‘์„ฑํ–ˆ๋˜ if else ๊ตฌ๋ถ„์„ junit์˜ ๋ฒ„์ „์œผ๋กœ ์ „ํ™˜ํ•ด๋ณด์ž. ์ด๋Š” junit์—์„œ assertThat์ด๋ผ๋Š” ์Šคํƒœํ‹ฑ ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

assetThat(user2.getName(), is(user.getName()));

assertThat() ๋ฉ”์†Œ๋“œ๋Š” ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ๊ฐ’์„ ๋’ค์— ๋‚˜์˜ค๋Š” ๋งค์ฒ˜(matcher)๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” ์กฐ๊ฑด์œผ๋กœ ๋น„๊ตํ•ด์„œ ์ผ์น˜ํ•˜๋ฉด ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ€๊ณ , ์•„๋‹ˆ๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๋„๋ก ๋งŒ๋“ค์–ด์ค€๋‹ค. is()๋Š” ๋งค์ฒ˜์˜ ์ผ์ข…์œผ๋กœ equals()๋กœ ๋น„๊ตํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์„ ๊ฐ€์กŒ๋‹ค.

๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ 2๋ฒˆ์งธ if๋ฌธ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

asserThat(user2.getPassword(), is(user.getPassword()))

์ค‘์š”ํ•œ ๊ฒƒ์€ Junit์€ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฑฐ๋‚˜ assertThat()์—์„œ ์‹คํŒจํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ–ˆ๋‹ค๊ณ  ์ธ์‹ํ•œ๋‹ค. โ€œํ…Œ์ŠคํŠธ ์„ฑ๊ณตโ€์ด๋ผ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๊ตณ์ด ์ถœ๋ ฅํ•  ํ•„์š”๋Š” ์—†๋‹ค. Junit์ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‚˜๋ฉด ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์•Œ๋ ค์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์ œ ์•ž์„œ ์ž‘์„ฑํ–ˆ๋˜ UserDaoTest๋ฅผ junit์œผ๋กœ ๋ณ€๊ฒฝํ•œ ์ฝ”๋“œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Asset.assertThat;
//...
public class UserDaoTest {
  @Test
  public void addAndGet() throws SQLException {
    ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
    
    UserDao dao = context.getBean("userDao", UserDao.class);
    User user = new User();
    
    user.setId("gyumee");
    user.setName("๋ฐ•์„ฑ์ฒ ");
    user.setPassword("spring01");
    
    dao.add(user);
    
    User user2 = dao.get(user.getId());
    
    assertThat(user2,getName(), is(user.getName()));
    assertThat(user2.getPassword(), is(user.getPassword));
  }
}

์ฝ”๋“œ๋งŒ ๋งŒ๋“ ๋‹ค๊ณ  ๋์ด ์•„๋‹ˆ๊ณ  junit๋„ ์ž๋ฐ” ์ฝ”๋“œ์ž„์œผ๋กœ ์–ด๋””์„ ๊ฐ€ ํ•œ๋ฒˆ์€ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ด์ค˜์•ผํ•œ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ ์–ด๋””์—๋“  main() ๋ฉ”์†Œ๋“œ๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•˜๊ณ  ๊ทธ ์•ˆ์— JUnitCore ํด๋ž˜์Šค์˜ main ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ๋Š” ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ๋ฉ”์†Œ๋“œ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” @Test ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ๊ฐ€์ง„ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ ๋„ฃ์–ด์ค€๋‹ค. UserDaoTest๋ฅผ ์‹คํ–‰ํ•  ํ…Œ๋‹ˆ ๋ฆฌ์Šค 2-6๊ณผ ๊ฐ™์ด springbook.user.dao.UserDaoTest๋ผ๋Š” ๊ฐ’์„ ๋„˜๊ฒจ์ค€๋‹ค.

import org.junit.runner.JUnitCore;
// ...
public static void main(String[] args) {
  JUnitCore.main("springbook.user.dao.UserDaoTest");
}

ํ•ด๋‹น main()๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฉ”์„ธ์ง€๊ฐ€ ์ถœ๋ ฅ๋˜๋ฉฐ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

JUnit version 4.7
Time: 0.578
OK 1 (test)

JUnit์˜ ๋ฒ„์ „๊ณผ ๊ฑธ๋ฆฐ ์‹œ๊ฐ„, ์„ฑ๊ณตํ•œ ํ…Œ์ŠคํŠธ ๊ฐฏ์ˆ˜๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. ์ด๋•Œ ๋งŒ์•ฝ์— ์‹คํŒจํ•˜๋ฉด ์‹คํŒจํ•œ ๋ฉ”์†Œ๋“œ์™€ ์™œ ์‹คํŒจํ–ˆ๋Š”์ง€ ์•Œ๋ ค์ค€๋‹ค.

๐Ÿ“Œ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ์˜ ์ผ๊ด€์„ฑ

UserDaoTest๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ํ•ญ์ƒ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด, ์ด์ „ ํ…Œ์ŠคํŠธ ๋•Œ๋ฌธ์— DB์— ๋“ฑ๋ก๋œ ์ค‘๋ณต ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์€ addAndGet() ํ…Œ์ŠคํŠธ๋ฅผ ๋งˆ์น˜๊ณ  ๋‚˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ๋“ฑ๋กํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด๋ฅผ ์‚ญ์ œํ•˜๊ณ  ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์ด์ „ ์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด ๋†“๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ…Œ์ŠคํŠธ๋ฅผ ์•„๋ฌด๋ฆฌ ๋ฐ˜๋ณตํ•˜์—ฌ ์‹คํ–‰ํ•ด๋„ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๊ณ , ์ด๋Ÿฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์–ด์•ผ ์ œ๋Œ€๋กœ ๋œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ผ๊ด€์„ฑ ์žˆ๋Š” ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด UserDaoTest์— ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

  • deleteAll(), getCount()

    • deleteAll() : USER ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋ ˆ์ฝ”๋“œ๋ฅผ ์‚ญ์ œํ•ด์ฃผ๋Š” ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค. UserDao ํด๋ž˜์Šค์— ๋ฉ”์†Œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ž.
    public void deleteAll() throws SQLException {
      connection c = dataSource.getConnection();
        
      PrepareStatement ps = c.prepareStatement("delete from users");
      ps.executeUpdate();
        
      ps.close();
      c.close();
    }
    

    add()์™€ ๋น„์Šทํ•œ๋ฐ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์ด ์—†์œผ๋ฏ€๋กœ ๋” ๋‹จ์ˆœํ•˜๋‹ค.

    • getCount(): ๋‘ ๋ฒˆ์งธ๋กœ ์ถ”๊ฐ€ํ•  ๊ฒƒ์€ getCount()๋กœ USER ํ…Œ์ด๋ธ”์˜ ๋ ˆ์ฝ”๋“œ ๊ฐœ์ˆ˜๋ฅผ ๋Œ๋ ค์ค€๋‹ค. ์ด๋Š” get ๋ฉ”์†Œ๋“œ์™€ ๋น„์Šทํ•œ ๊ตฌ์กฐ์ด๋‹ค.
    public int getCount() throws SQLException {
    	Connection c = dataSoutce.getConnection();
        
      PrepareStatement ps = c.prepareStatement("select count(*) from users");
        
      ResultSet rs = ps.executeQuery();
      rs.next();
      int count = rs.getInt(1);
        
      rs.close();
      ps.close();
      c.close();
        
      return count;
    }
    

addAndGet()ํ…Œ์ŠคํŠธ์˜ ๋ถˆํŽธํ•œ ์ ์€ ์‹คํ–‰ ์ „์— ์ˆ˜๋™์œผ๋กœ USER ํ…Œ์ด๋ธ”์˜ ๋‚ด์šฉ์„ ๋ชจ๋‘ ์‚ญ์ œํ•ด์ค˜์•ผ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ํ•˜์ง€๋งŒ deleteAll()์„ ์‚ฌ์šฉํ•˜๋ฉด ํ…Œ์ด๋ธ”์˜ ๋ชจ๋“  ๋‚ด์šฉ์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์‹คํ–‰ํ•˜๋ฉด ์ข‹์„ ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ ์ž˜ ์ž‘๋™ํ•˜๋ฉด ํ…Œ์ŠคํŠธ ๋•Œ๋งˆ๋‹ค ์ผ์ผ์ด ํ…Œ์ด๋ธ”์„ ์‚ญ์ œํ•˜์ง€ ์•Š์•„๋„ ๊ดœ์ฐฎ์„ ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ deleteAll()์ž์ฒด๋„ ๊ฒ€์ฆ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์„ ๊ฐ์•ˆํ•˜๋ฉด ๋ฌดํ„ฑ๋Œ€๊ณ  ํ…Œ์ŠคํŠธ์— ์ ์šฉํ•˜๊ธฐ์—๋Š” ๋ถ€๋‹ด์Šค๋Ÿฝ๋‹ค. ๋”ฐ๋ผ์„œ getCount()๋„ ํ•จ๊ป˜ ์ ์šฉํ•ด๋ณด์ž. ๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ ๋˜ ๋ฌธ์ œ๊ฐ€ getCount()๋„ ๊ฒ€์ฆ๋˜์ง€๋Š” ์•Š์•˜๋‹ค. ๊ทธ๋ž˜์„œ getCount()์— ๋Œ€ํ•œ ๊ฒ€์ฆ ์ž‘์—…์„ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•œ๋‹ค. ๋ฌผ๋ก  ์ด ๋ชจ๋“  ์ฝ”๋“œ๋Š” addAndGet()๋ฉ”์†Œ๋“œ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

@Test
public void addAndGet() throws SQLException{
  //...
  dao.deleteAll();
  assertThat(dao.getCount(), is(0));
  
  User user = new User();
  user.setId("gyumee");
  user.setName("๋ฐ•์„ฑ์ฒ ");
  user.setPassword("springno01");
  
  dao.add(user);
  assertThat(dao.getCount(), is(1));
  
  User user2 = dao.get(user.getId());
  
  assertThat(user2.getName(), is(user.getName()));
  assertThat(user2.getPassword(), is(user.getPassword()));
}

Junit์€ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค ์•ˆ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๊ฐ€ ๋“ค์–ด๊ฐ€๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•œ๋‹ค. @Test๊ฐ€ ๋ถ™์–ด ์žˆ๊ณ  public ์ ‘๊ทผ์ž๊ฐ€ ์žˆ์œผ๋ฉฐ ๋ฆฌํ„ด ๊ฐ’์ด voidํ˜•์ด๊ณ  ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋‹ค๋Š” ์กฐ๊ฑด์„ ์ง€ํ‚ค๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ธฐ ์ „์— User ํด๋ž˜์Šค์— ํ•œ ๋ฒˆ์— ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ๋„๋ก ์ดˆ๊ธฐํ™”๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. User ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋งŒ๋“ค๊ณ  ๊ฐ’์„ ๋„ฃ์–ดํ– ํ•˜๋‹ˆ, ํ•œ ๋ฒˆ์— ์„ค์ • ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด๋‘๋ฉด ํŽธ๋ฆฌํ•˜๋‹ค.

public User(String id, String name, String password) {
  this.id = id;
  this.name = name;
  this.password = password;
}

public User() { // โ†’ ์ž๋ฐ”๋นˆ์˜ ๊ทœ์•ฝ์„ ๋”ฐ๋ฅด๋Š” ํด๋ž˜์Šค์— ์ƒ์„ฑ์ž๋ฅผ
  							// ๋ช…์‹œ์ ์œผ๋กœ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋Š” ๋””ํดํŠธ ์ƒ์„ฑ์ž๋„ ํ•จ๊ป˜
  							// ์ •์˜ํ•ด์ฃผ๋Š” ๊ฒƒ์„ ์žŠ์ง€๋ง์ž.
}

์œ„๋ฅผ ์ด์šฉํ•˜๋ฉด addAndGet() ํ…Œ์ŠคํŠธ์˜ ์ฝ”๋“œ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋žตํžˆ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

UserDao dao = context.getBean("userDao", UserDao.class);
User user = new User("gyumee", "๋ฐ•์„ฑ์ฒ ", "springno01");

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ getCount()์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

@Test
public void count() throws SQLException {
  ApplicationContext context = new GenericXmlApplicaiotnConext("applicationContext.xml");
  
  UserDao dao = context.getBean("userDao", UserDao.class);
  User user1 = new User("gyumee", "๋ฐ•์„ฑ์ฒ ", "springno1");
  User user2 = new User("leegw700", "์ด๊ธธ์›", "springno2");
  User user3 = new User("bumjin", "๋ฐ•๋ฒ”์ง„", "springno3");
  
  dao.deleteAll();
  assertThat(dao.getCount(), is(0));
  
  dao.add(user1);
  assertThat(dao.getCount(), is(1));
  
  dao.add(user2);
  assertThat(dao.getCount(), is(2));
  
  dao.add(user3);
  assertThat(dao.getCount(), is(3));
}

๊ทธ๋Ÿฐ๋ฐ get()์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ฃผ์–ด์ง„ id์— ํ•ด๋‹นํ•˜๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ธ์ง€, ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ์•„๋ฌด๊ฑฐ๋‚˜ ๊ฐ€์ ธ์˜จ ๊ฒƒ์ธ์ง€ ํ…Œ์ŠคํŠธ์—์„œ ๊ฒ€์ฆํ•˜์ง€ ๋ชปํ–ˆ๋‹ค. ํ•ด๋‹น ๋ถ€๋ถ„์€ User๋ฅผ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•ด์„œ id๋ฅผ ์ •ํ™•ํžˆ ๊ฐ€์ ธ์™”๋Š”์ง€ ํ™•์ธํ•ด๋ณด๋ฏ€๋กœ์„œ addAndGet()๋ฅผ ๋ณด์™„ํ•  ์ˆ˜ ์žˆ๋‹ค.

@Test
public void addAndGet() throws SQLException {
  // ...
  
  UserDao dao = context.getBean("userDao", UserDao.class);
  user user1 = new User("gyumee", "๋ฐ•์„ฑ์ฒ ", "springno1");
  user user2 = new User("leegw700", "์ด๊ธธ์›", "springno2");
  
  dao.deleteAll();
  asserThat(dao.getCount(), is(0));
  
  dao.add(user1);
  dao.add(user2);
  assertThat(dao.getCount(), is(2));
  
  User userget1 = dao.get(user1.getId());
  assertThat(userget1.getName(), is(user1.getName()));
  assertThat(userget1.getPassword(), is(user1.getPassword()));
  
  User userget2 = dao.get(user2.getId());
  assertThat(userget2.getName(), is(user2.getName()));
  assertThat(userget2.getPassword(), is(user2.getPassword()));
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด id ๊ฐ’์— ์ ‘๊ทผํ•œ user ์ •๋ณด์™€ ์ €์žฅํ•œ user ์ •๋ณด์™€ ๋™์ผํ•จ์„ ํ™•์ธํ•˜๋ฏ€๋กœ์จ get()์— ๋Œ€ํ•ด ์‹ ๋ขฐ๋ฅผ ์–ป๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทผ๋ฐ ๋งŒ์•ฝ์— id๋กœ ์ ‘๊ทผํ–ˆ๋Š”๋ฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์ด๋Ÿด ๋•Œ๋Š” 2๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. null๊ณผ ๊ฐ™์€ ํŠน๋ณ„ํ•œ ๊ฐ’์„ ๋ฆฌํ„ด
  2. id ์ •๋ณด๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋‹ค๊ณ  ๋ฆฌํ„ด

๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ด ์žˆ๋Š”๋ฐ, ์ผ๋‹จ 2๋ฒˆ์˜ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

์ผ๋‹จ ์Šคํ”„๋ง์—์„œ EmptyResultDataAccessException์€ ์˜ˆ์™ธ ํด๋ž˜์Šค์ด๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด UserDao์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•ด ๊ฐ€์ ธ์˜จ ๊ฒฐ๊ณผ์— ์•„๋ฌด๊ฒƒ๋„ ์—†์„ ๋•Œ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋„๋ก ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ฐ€์žฅ ํฐ ๋ฌธ์ œ๋Š” ์ด๋Ÿฌํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š”๊ฐ€? ์ด๋‹ค. ์™œ๋ƒํ•˜๋ฉด, ํ…Œ์ŠคํŠธ ์ค‘์— ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง€๋ฉด ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์˜ ์‹คํ–‰์€ ์ค‘๋‹จ๋˜๊ณ  ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทผ๋ฐ ์ด๋ฒˆ์—๋Š” ๋ฐ˜๋Œ€๋กœ ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง€์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž ์ •์ƒ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๋ฉด ์ด ๋˜ํ•œ ์˜ˆ์™ธ๋ฅผ ์•Œ๊ธฐ์œ„ํ•œ ํ…Œ์ŠคํŠธ๋Š” ์‹คํŒจํ•œ ๊ฒƒ ์•„๋‹Œ๊ฐ€? ์ฆ‰ ์˜ˆ์™ธ ๋ฐœ์ƒ ์—ฌ๋ถ€๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋ฆฌํ„ด ๊ฐ’์„ ๋น„๊ตํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ํ™•์ธํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด assertThat()์œผ๋กœ๋Š” ํ™•์ธ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋ง์ด ๊ธธ์–ด์กŒ๋Š”๋ฐ, ์ด ๋ถ€๋ถ„์„ Junit์—์„œ ํŠน๋ณ„ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ผ๋‹จ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ํ•˜๋‚˜ ๋” ์ถ”๊ฐ€ํ•˜์ž. ๋ฐฉ๋ฒ•์€ ๊ฐ„๋‹จํ•˜๋‹ค.

  1. ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ง€์šด๋‹ค.
  2. ์กด์žฌํ•˜์ง€ ์•Š๋Š” id๋กœ get()์„ ํ˜ธ์ถœํ•œ๋‹ค.
  3. ์ด๋•Œ EmptyResultAccessException์ด ๋˜์ ธ์ง€๋ฉด ์„ฑ๊ณต์ด๊ณ  ์•„๋‹ˆ๋ฉด ์‹คํŒจ๋‹ค.
@Test(expected=EmptyResultDataAccessException.class) // โ†’ ํ…Œ์ŠคํŠธ ์ค‘์— ๋ฐœ์ƒํ•œ ๊ฒƒ์œผ๋กœ ๊ธฐ๋Œ€ํ•˜๋Š” ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ์ง€์ •
public void getUserFailure() Throws SQLException {
  ApplicationContext context = new GenericXmlApplicationContext("applicationContext");
  
  UserDao dao = context.getBean('userDao', UserDao.class);
  dao.deleteAll();
  assertThat(dao.getCount(), is(0));
  
  dao.get("unknown_id");
}

Test์ฝ”๋“œ๋Š” ๊ฐ„๋‹จํ•˜๋‹ค. ๋ชจ๋“  User ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์šฐ๊ณ  ์กด์žฌํ•˜์ง€ ์•Š๋Š” id๋กœ get() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒŒ ์ „๋ถ€๋‹ค. ์ด ํ…Œ์ŠคํŠธ์—์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ @Test ์• ๋…ธํ…Œ์ด์…˜์˜ expected ์—˜๋ฆฌ๋ฉ˜ํŠธ๋‹ค. excepted๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ ์‹คํ–‰ ์ค‘์— ๋ฐœ์ƒํ•˜๋ฆฌ๋ผ ๊ธฐ๋Œ€ํ•˜๋Š” ์˜ˆ์™ธ ํด๋ž˜์Šค๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

@Test์— expected๋ฅผ ์ถ”๊ฐ€ํ•ด๋†“์œผ๋ฉด, ๋ณดํ†ต์˜ ํ…Œ์ŠคํŠธ์™€๋Š” ๋ฐ˜๋Œ€๋กœ ์ •์ƒ์ ์œผ๋กœ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งˆ์น˜๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๊ณ  expected์—์„œ ์ง€์ •ํ•œ ์˜ˆ์™ธ๊ฐ€ ๋˜์ ธ์ง€๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ•œ๋‹ค.

๋ฐ˜๋“œ์‹œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์œผ๋‹ˆ ๊ธฐ์–ตํ•˜์ž. ๊ทผ๋ฐ ์›ƒ๊ธด๊ฑด ์œ„์— ์ฝ”๋“œ ๋Œ๋ฆฌ๋ฉด ์‹คํŒจํ•œ๋‹ค. ์™œ๋ƒ๋ฉด get()๋ฉ”์†Œ๋“œ์—์„œ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์˜ ์ฒซ ๋ฒˆ์งธ ํ–‰์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ํ•˜๋Š” rs.next()๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๊ฐ€์ ธ์˜ฌ ๋กœ์šฐ๊ฐ€ ์—†๋‹ค๋Š” SQLException์ด ๋ฐœ์ƒํ•  ๊ฒƒ์ด๊ณ  ์ด๊ฑด ๋‹น์—ฐํ•˜๋‹ค ์•„์ง UserDao์— ์† ์•ˆ๋Œ”๋‹ค.

์œ„์ฝ”๋“œ๋ฅผ ์„ฑ๊ณต์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ๋Š” get๋ฉ”์†Œ๋“œ๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค. get์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์œผ๋ฉด EmptyResultDataAccessException์„ ๋˜์ง€๋ฉด ๋œ๋‹ค.

public User get(String id) throws SQLException {
  // ... 
  ResultSet rs = ps.executeQuery();
  
  User user = null; // โ†’ User๋Š” null ์ƒํƒœ๋กœ ์ดˆ๊ธฐํ™”ํ•ด๋†“๋Š”๋‹ค.
  if(rs.next()) {
    user = new User();
    user.setId(rs.getSring("id"));
    user.setName(rs.getString('name'));
    user.setPassword(rs.getString("password")); // id๋ฅผ ์กฐ๊ฑด์œผ๋กœ ํ•œ ์ฟผ๋ฆฌ์˜ ๊ฒฐ๊ณผ๊ฐ€ ์žˆ์œผ๋ฉด User
    // ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ฐ’์„ ์ค€๋‹ค.
  }
  rs.close();
  ps.close();
  c. close();
  
  if (user == null) throw new EmptyResultDataAccessException(1);
  
  return user;
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์ •์ƒ์ ์œผ๋กœ ์ž‘์„ฑ๋˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ง€๊ธˆ ์šฐ๋ฆฌ๊ฐ€ ์ง„ํ–‰ํ•œ ์ƒํ™ฉ์„ ๋Œ์ด์ผœ๋ณด๋ฉด ํ•œ ๊ฐ€์ง€ ์žฌ๋ฐŒ๋Š” ์ ์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๊ฑด ๋จผ์ € ๊ธฐ๋Šฅ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ›„ ๊ธฐ๋Šฅ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ–ˆ๋‹ค๋Š” ์ ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๊ณผ์ •์„ TDD(Test Driven Development)๋˜๋Š” TFD(Test First Development)๋ผ๊ณ  ํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์„ ๋ณด์•˜์„ ๋•Œ TDD๋Š” ๋งค์šฐ ์ค‘์š”ํ•œ ๊ฐœ๋ฐœ ๋ฐฉ์‹์ด๋ผ๋Š” ๊ฒƒ์„ ์žŠ์ง€๋ง์ž.

๋˜ํ•œ test์ฝ”๋“œ๋„ ๋ฆฌํŽ™ํ† ๋ง์˜ ๋Œ€์ƒ์ด๋œ๋‹ค. ์ข€๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹์•„ํ•˜๋Š” ์ฝ”๋“œ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณผ์ •์€ ๊ธฐ๋Šฅ ๋ถ€๋ฌธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋„ ํ•„์š”ํ•˜๋‹ค.

์šฐ๋ฆฌ๋Š” ์ง€๊ธˆ๊นŒ์ง€ 3๊ฐœ์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค. UserDaoTest์ฝ”๋“œ๋ฅผ ์ž˜ ์ƒํŽด๋ณด๋ฉด ๊ธฐ๊ณ„์ ์œผ๋กœ ๋ฐ˜๋ณต๋˜๋Š” ๋ถ€๋ถ„์ด ๋ˆˆ์— ๋ˆ๋‹ค.

ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
User dap = context.getBean("userDao",UserDao.class);

์ด ๋ถ€๋ถ„์„ ๋ณ„๋„์˜ ๋ฉ”์†Œ๋“œ๋กœ ์˜ฎ๊ธฐ๊ณ  ํ•ด๋‹น ๋ถ€๋ถ„ ์œ„์— @Before ์• ๋…ธํ…Œ์ด์…˜์„ ์ ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์†Œ๋“œ๋ฅผ setUp()์ด๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด UserDaoTest์˜ ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๊ณ  ๋” ๊น”๋”ํ•œ ๋А๋‚Œ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ํ•ด๋‹น ๋ถ€๋ถ„์€ Junit์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

import org.junit.Before;
// ...
public class UserDaoTest {
  private UserDao dao;
  
  @Before
  public void setUp() {
    ApplicationContext context = new GenericXmlApplicationContextx("applicationContext.xml");
    this.dao = context.getBean("UserDao", UserDao.class);
  }
  // ...
  @Test
  public void addAndGet() throws SQLException {
    // ...
  }
  
  @Test
  public void count() throws SQLException {
    // ...
  }
  
  @Test(expected=EmptyResultDataAccessException.class)
  public void getUserFailure() throws SQLException {
    // ...
  }
}

๋ฌผ๋ก  ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” junit์˜ ๋™์ž‘ ๋ฐฉ์‹์„ ์ข€ ์•Œ์•„๋ด์•ผํ•œ๋‹ค.

  1. ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— @Test๊ฐ€ ๋ถ™์€ public์ด๊ณ  voidํ˜•์ด๋ฉฐ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—†๋Š” ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ๋‘ ์ฐพ๋Š”๋‹ค.
  2. ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ ๋‹ค.
  3. @Before๊ฐ€ ๋ถ™์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์‹คํ–‰ํ•œ๋‹ค.
  4. @Test๊ฐ€ ๋ถ™์€ ๋ฉ”์†Œ๋“œ๋ฅผ ํ•˜๋‚˜ ํ˜ธ์ถœํ•˜๊ณ  ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ๋ฅผ ์ €์žฅํ•ด๋‘”๋‹ค.
  5. @After๊ฐ€ ๋ถ™์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์‹คํ–‰ํ•œ๋‹ค.
  6. ๋‚˜๋จธ์ง€ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ์— ๋Œ€ํ•ด 2~5๋ฒˆ์„ ๋ฐ˜๋ณตํ•œ๋‹ค.
  7. ๋ชจ๋“  ํ…Œ์ŠคํŠธ์˜ ๊ฒฐ๊ณผ๋ฅผ ์ข…ํ•ฉํ•ด์„œ ๋Œ๋ ค์ค€๋‹ค.

์‹ค์ œ๋กœ๋Š” ์ด๋ณด๋‹ค ๋” ๋ณต์žกํ•˜๋‹ค๊ณ  ํ•œ๋‹ค. ๋Œ€๋žต์ ์œผ๋กœ junit ํ…Œ์ŠคํŠธ๋Š” ์œ„์˜ 7๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์„œ ์ง„ํ–‰๋œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

๊ทผ๋ฐ ์—ฌ๊ธฐ์„œ Before์™€ After๊ฐ€ ๋„๋Œ€์ฒด ๋ญ๋ƒ? ์ƒ๊ฐ์ด ๋“ค ์ˆ˜ ์žˆ๋Š”๋ฐ, ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์ „์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ Before, ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋œ ํ›„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ After๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ Junit์€ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ฒŒ๋” ๋งŒ๋“ค์–ด์ ธ ์žˆ๋‹ค. ์ด์œ ๋Š” ๊ฐ ํ…Œ์ŠคํŠธ๊ฐ€ ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰๋จ์„ ํ™•์‹คํžˆ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋‹ค. ๋ฌผ๋ก  ๊ฒฝ์šฐ์— ๋”ฐ๋ผ์„œ ํšจ์œจ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ ๊ณตํ†ต์ ์ธ ํŠน์„ฑ์„ ์ง€๋‹Œ ํ…Œ์ŠคํŠธ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ์•„์„œ ๋ณ„๋„์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋กœ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•๋„ ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ •๋ณด๋‚˜ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ”ฝ์Šค์ฒ˜(fixture)๋ผ๊ณ  ํ•œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ํ”ฝ์Šค์ฒ˜๋Š” ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ์—์„œ ๋ฐ˜๋ณต์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— @Before ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•ด์ฃผ๋ฉด ํŽธ๋ฆฌํ•˜๋‹ค. UserDaoTest์—์„œ๋Š” dao๊ฐ€ ํ”ฝ์Šค์ฒ˜์ด๋‹ค.

public class UserDaoTest{
  private UserDao dao;
  private User user1;
  private User user2;
  private User user3;
	
  @Before
  public void setUp() {
    //...
    this.user1 = new User("gyumee", "๋ฐ•์„ฑ์ฒ ", "springno1");
    this.user2 = new User("leegw700", "์ด๊ธธ์›", "springno2");
    this.user3 = new User("bumjin", "๋ฐ•๋ฒ”์ง„", "springno3");
  }
  // ...
}

๐Ÿ“Œ ์นจํˆฌ์  ๊ธฐ์ˆ ๊ณผ ๋น„์นจํˆฌ์  ๊ธฐ์ˆ 

์นจํˆฌ์  ๊ธฐ์ˆ ์€ ๊ธฐ์ˆ ์„ ์ ์šฉํ–ˆ์„ ๋•Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์— ๊ธฐ์ˆ  ๊ด€๋ จ API๊ฐ€ ๋“ฑ์žฅํ•˜๊ฑฐ๋‚˜ ํŠน์ • ์ธํ„ฐํŽ˜์ด์Šค๋‚˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์ œํ•˜๋Š” ๊ธฐ์ˆ ์„ ๋งํ•œ๋‹ค. ์นจํˆฌ์  ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๊ฐ€ ํ•ด๋‹น ๊ธฐ์ˆ ์— ์ข…์†๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค.

๋น„์นจํˆฌ์  ๊ธฐ์ˆ ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ๋‹ด์€ ์ฝ”๋“œ์— ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ๊ธฐ์ˆ ์— ์ข…์†์ ์ด์ง€ ์•Š์€ ์ˆœ์ˆ˜ํ•œ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ์Šคํ”„๋ง์€ ์ด๋Ÿฐ ๋น„์นจํˆฌ์ ์ธ ๊ธฐ์ˆ ์˜ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ์ด๋‹ค. (์ปจํ…Œ์ด๋„ˆ ์—†๋Š” DIํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์—)

๐Ÿ“Œ ๋™๋“ฑ๋ถ„ํ• ๊ณผ ๊ฒฝ๊ณ„๊ฐ’ ๋ถ„์„

  • ๋™๋“ฑ๋ถ„ํ• 
    • ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋Š” ๊ฐ’์˜ ๋ฒ”์œ„๋ฅผ ๊ตฌ๋ถ„ํ•ด์„œ ๊ฐ ๋Œ€ํ‘œ ๊ฐ’์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋งํ•œ๋‹ค. ์–ด๋–ค ์ž‘์—…์˜ ๊ฒฐ๊ณผ true, false ๋˜๋Š” ์˜ˆ์™ธ ๋ฐœ์ƒ ์„ธ ๊ฐ€์ง€๋ผ๋ฉด ๊ฐ ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๋Š” ์ž…๋ ฅ ๊ฐ’์ด๋‚˜ ์ƒํ™ฉ์˜ ์กฐํ•ฉ์„ ๋งŒ๋“ค์–ด ๋ชจ๋“  ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • ๊ฒฝ๊ณ„๊ฐ’ ๋ถ„์„
    • ์—๋Ÿฌ๋Š” ๋™๋“ฑ๋ถ„ํ•  ๋ฒ”์œ„์˜ ๊ฒฝ๊ณ„์—์„œ ์ฃผ๋กœ ๋งŽ์ด ๋ฐœ์ƒํ•œ๋‹ค๋Š” ํŠน์ง•์„ ์ด์šฉํ•ด์„œ ๊ฒฝ๊ณ„์˜ ๊ทผ์ฒ˜์— ์žˆ๋Š” ๊ฐ’์„ ์ด์šฉํ•ด ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋ณดํ†ต ์ˆซ์ž์˜ ์ž…๋ ฅ ๊ฐ’์ธ ๊ฒฝ์šฐ 0์ด๋‚˜ ๊ทธ ์ฃผ๋ณ€ ๊ฐ’ ๋˜๋Š” ์ •์ˆ˜์˜ ์ตœ๋Œ€๊ฐ’, ์ตœ์†Œ๊ฐ’ ๋“ฑ์œผ๋กœ ํ…Œ์ŠคํŠธํ•ด๋ณด๋ฉด ๋„์›€์ด ๋  ๋•Œ๊ฐ€ ๋งŽ๋‹ค.