2.0 스터디
Comment
•
제어의 역전 개념이 JUnit같은 테스트용 프레임워크에도 적용되는걸 처음 깨달음
•
테스트를 작은 단위로 쪼갠다
= 최소한의 관심사에 집중한다
= 꼼꼼하게 테스트할 수 있다
어떤 언어/프레임워크의 테스트에도 당연하겠지만 스프링에서는 ‘다른 레이어의 간섭 최소화’도 장점에 포함될듯
•
2.1 UserDaoText 다시보기
package springbook.user.dao;
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import springbook.user.domain.User;
public class UserDaoTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);
UserDao dao = context.getBean("userDao", UserDao.class);
User user = new User();
user.setId("whiteship");
user.setName("name");
user.setPassword("married");
dao.add(user);
System.out.println(user.getId() + "register succeed");
User user2 = dao.get(user.getId());
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user2.getId() + "get succeed");
}
}
Java
복사
2.1.1. 테스트의 유용성
•
테스트 = 개발자가 예상하고 의도했던 대로 코드가 정확히 동작하는지 확인해서, 만든 코드를 확신할 수 있게 해주는 작업
•
테스트의 결과가 원하는 대로 나오지 않는 경우 → 코드나 설계에 결함이 있음 → 결함을 제거해가는 작업(디버깅)을 거치게 됨 → 최종적으로 테스트 성공 시 모든 결함이 제거되었다는 확신
2.1.2. UserDaoTest에서의 문제 ⇒ 작은 단위의 테스트
•
DAO에 대한 테스트인데, 서비스 클래스/컨트롤러/JSP 뷰 등 모든 레이어의 기능을 다 만들고 나서 테스트가 가능하다는 점이 문제
테스트 실패 시 어디서 문제가 생겼는지도 찾아야 함
⇒ 하나의 테스트를 수행하는 데 참여하는 클래스와 에러 메세지가 너무 많음
•
작은 단위의 테스트 ⇒ 단위 테스트(Unit Test)
◦
테스트하고자 하는 대상이 명확하다면, 그 대상에만 집중해서 테스트하는 것이 바람직
◦
하나의 관심에만 집중해서 효율적으로 테스트할 만한 범위의 단위
◦
테스트는 가능하면 작은 단위로 쪼개서 집중해야 함
◦
통제할 수 없는 외부의 리소스에 의존하는 테스트는 단위 테스트가 아니라고 보기도 함
Point out
이전 장에서 스프링에서 제일 중요한 건 오브젝트이며, 오브젝트는 하나의 관심사에 충실해야 한다고 강조(분리와 확장)
마찬가지로 테스트에서도 ‘한 가지 관심’에 집중할 수 있게 작은 단위로 테스트를 쪼갬
•
어쨌든 UserDaoTest 클래스는 UserDao가 작은 단위의 데이터에 액세스하는 기능을 수행하는지 테스트하기 위해 만들어졌고, 다른 레이어가 참여하지 않기 때문에 단위테스트긴 하다
2.1.3. 그럼에도 불구하고 문제점
1.
수동 확인 작업이 귀찮음
2.
실행 작업이 귀찮음
2.2 UserDaoTest 개선
2.2.1. 수동 확인 작업이 귀찮음 → 테스트 검증을 자동화
문제의 부분
User user2 = dao.get(user.getId());
System.out.println(user2.getName());
System.out.println(user2.getPassword());
System.out.println(user2.getId() + "get succeed");
Java
복사
어떤 부분을 고쳐야 하는가
if (!user.getName().equals(user2.getName()) {
System.out.println("테스트 실패 (name)");
}
else if (!user.getPassword().equals(user2.getPassword()) {
System.out.println("테스트 실패 (password)");
}
else {
System.out.println("조회 테스트 성공");
}
Java
복사
•
코드를 통해 조회된 객체의 파라미터 값을 equal 메소드로 비교함으로서 육안으로의 확인 없이 테스트 성공/실패 여부 출력
•
눈으로 확인하는 ‘번거로움’ 없이 정상적으로 개발이 된 것을 확인 가능
2.2.2. 실행 작업이 귀찮음 → JUnit 프레임워크 활용
main() 메소드의 한계 ⇒ JUnit
•
자바 테스팅 프레임워크, 자바로 단위 테스트 만들 때 유용함
•
IoC ⇒ 프레임워크가 클래스에 대한 제어 권한을 넘겨받아 애플리케이션의 흐름을 제어
⇒ 클래스의 오브젝트를 생성/실행하는 일이 프레임워크에 의해 진행 ⇒ main() 메소드 불필요
JUnit 프레임워크의 요구
1.
메소드가 public으로 선언되어야 함
2.
메소드에 @Test 어노테이션 붙여줘야 함
그래서 변경하면?
package springbook.user.dao;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.sql.SQLException;
import org.junit.Test;
import org.junit.runner.JUnitCore;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import springbook.user.domain.User;
public class UserDaoTest {
@Test
public void andAndGet() throws SQLException {
ApplicationContext context = new GenericXmlApplicationContext("applicationContext.xml");
UserDao dao = context.getBean("userDao", UserDao.class);
User user = new User();
User user = new User();
user.setId("whiteship");
user.setName("name");
user.setPassword("married");
dao.add(user);
User user2 = dao.get(user.getId());
assertThat(user2.getName(), is(user.getName()));
assertThat(user2.getPassword(), is(user.getPassword()));
}
public static void main(String[] args) {
JUnitCore.main("springbook.user.dao.UserDaoTest");
}
}
Java
복사