티스토리 뷰

애플리케이션은 계속 변하고 복잡해져 간다. 그 변화에 대응하는 첫번째 전략이 확장과 변화를 고려한 객체지향적 설계와 그것을 효과적으로 담아낼 수 있는 IoC/DI 같은 기술이라면, 두 번째 전략은 만들어진 코드를 확신하게 할 수 있게 해주고, 변화에 유연하게 대처할 수 있는 자신감을 주는 테스트 기술이다.

웹을 통한 DAO 테스트 방법의 문제점

보통 웹 프로그램에서 사용하는 DAO의 테스트 하는 방법은 웹 화면을 띄워 폼을 열고, 값을 입력한 뒤 버튼을 눌러 등록한다. 이렇게 웹 화면을 통해 값을 입력하고, 기능을 수행하고, 결과를 확인하는 방법은 가장 흔히 쓰이는 방법이지만, DAO에 대한 테스트로서는 단점이 너무 많다. 그렇다면 테스트를 어떻게 만들어야 이런 문제를 피할 수 있고, 효율적으로 활용할 수 있을지 생각해보자.

작은 단위의 테스트

테스트하고자 하는 대상이 명확하지 않으면 테스트 수행 과정도 복잡해지고, 오류가 발생했을 때 정확한 원인을 찾기 힘들어진다. 따라서 테스트는 가능하면 작은 단위로 쪼개서 집중할 수 있어야 한다.

이렇게 작은 단위의 코드에 대해 테스트를 수행한 것을 단위 테스트 라고 한다. 여기서 말하는 단위란 그 크기와 범위가 어느 정도인지 딱 정해진 건 아니다. 하나의 관심에 집중해서 효율적으로 테스트할 만한 범위의 단위라고 보면된다. 이렇게 작은 단위로 테스트가 필요한 이유는 개발자가 만든 코드가 의도한대로 동작하는지 개발자 스스로 빨리 확인받기 위해서다.

개발자를 위한 테스팅 프레임워크 JUnit

JUnit 은 자바의 표준 테스팅 프레임워크라고 불릴 만큼 폭넓게 사용되고 있다. 스프링을 학습하고 제대로 활용하려면 최소한의 JUnit 테스트 작성 방법과 실행 방법은 알고 있어야 한다.

JUnit5란?

이전 버전의 JUnit 과 다르게 JUnit5 는 세가지 다른 하위 프로젝트의 여러 모듈로 구성된다

JUnit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform

  • JUnit PlatformJVM 환경에서 테스트 프레임워크를 시작하는 기반 역할을 한다
  • Test Engine 을 사용하여 사용자 정의의 테스트 세트를 실행할 수 있는 JUnit Platform Suite Engine 을 제공한다
  • 유명한 IDE(Intellij,Eclipse,NetBeans) 와 Build Tool(Gradle,Maven) 에서도 지원한다

JUnit Jupiter

  • JUnit JupiterJUnit5 에서 테스트 및 확장을 작성하기 위한 새로운 프로그래밍과 확장 모델의 조합이다
  • Jupiter 하위 프로젝트는 플랫폼에서 Jupiter 기반 테스트를 실행할 수 있는 TestEngine 엔진을 제공한다

JUnit Vintage

  • JUnit VintageTestEngine 플랫폼에서 JUnit3JUnit4 기반 테스트를 실행할 수 있는 TestEngine 을 제공한다

지원하는 Java 버전

JUnit5 는 Java8 이상 버전이 필요하다. 하지만 이전 버전의 JDK 로 컴파일된 코드는 계속 테스트할 수 있다

Given-When-Then 패턴

Given-When-ThenBDD 의 일환으로 Dan North가 제안했습니다. 시나리오 작성을 세 가지의 섹션으로 나누는 것이다.

  • Given
    • 전제조건
  • When
    • 지정하는 동작
  • Then
    • 지정한 동작으로 인해 예상되는 변경 사항

예제

기능: 사용자 거래 주식
  시나리오: 거래가 종료되기 전에 사용자가 매도를 요청합니다.

  // Given
  내가 MSFT 주식 100주를 가지고 있다고 가정할 때
  그리고 저는 APPL 주식 150주를 가지고 있습니다.
  그리고 시간은 거래 종료 전입니다.

  // When
  MSFT 주식 20주를 매도할 것을 요청할 때

  // Then 
  그러면 MSFT 주식 80주가 있어야 합니다.
  그리고 나는 APPL 주식 150주를 가지고 있어야 합니다.
  그리고 MSFT 주식 20주에 대한 매도 주문을 실행했어야 합니다.

테스트 코드와 DI

public class UserDao {

  @Autowired
  private DataSource dataSource;


  public void add(User user) throws ClassNotFoundException, SQLException {
    Class.forName("com.mysql.jdbc.Driver");
    Connection c = dataSource.getConnection();

    PreparedStatement ps = c.prepareStatement(
        "insert into users(id,name,password) values(?,?,?)");
    ps.setString(1, user.getId());
    ps.setString(2, user.getName());
    ps.setString(3, user.getPassword());

    ps.executeUpdate();

    ps.close();
    c.close();
  }
}

public class UserDaoTest {

  @Test
  void test() throws SQLException, ClassNotFoundException {
    UserDao userDao = new UserDao();
    userDao.get("misoo");
  }
}

Spring Framework 의 도움을 받지 않은 순수 단위 테스트에서 @Autowired 를 사용하면 의존 관계 주입이 되지 않아 NPE 가 발생한다. 생성자 주입을 사용하여야 컴파일 시점에 객체를 주입받아 테스트 코드를 작성할 수 있다.

결론

스프링을 사용하는 개발자라면 자신이 만든 코드를 테스트로 검증하는 방법을 알고 있어야 하며, 테스트를 개발에 적극 활용할 수 있어야 한다. 테스트는 포괄적으로 작성해야 하며, 충분한 검증을 하지 않는 테스트는 없는 것보다 나쁠 수 있다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
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
글 보관함