토비의 스프링 2장을 읽으며

김다혜·2020년 3월 15일
0

토비의 스프링

목록 보기
2/5
post-thumbnail

2장은 '테스트'에 관련 내용이다. 테스트는 만들어진 코드를 확신할 수 있게 해주고, 변화에 유연하게 대처할 수 있는 자신감을 준다. 나는 '토비의 스프링'을 두 번째 읽기 때문에 junit5를 사용해서 테스트 해보기로 했다 😀

스프링의 🌻 테스트

✔️ 내가 예상하고 의도했던 대로 코드가 정확히 동작하는 지를 확인해서 만든 코드를 확신할 수 있게 해주는 작업이다.
✔️ 스프링을 학습하는 데 있어 가장 효과적인 방법 중 하나이다.
✔️ 기존에 만들어뒀던 기능들을 수정하는 경우, 수정한 코드에 영향을 받지 않고 여전히 잘 동작하는지를 확인할 수도 있다.

🤔 어떤 테스트가 좋은 테스트일까 ?

✔️ 테스트하고자 하는 대상이 명확하다면 그 대상에만 집중해서 테스트 하자. (작은 단위의 코드에 대해 테스트를 수행하는 것을 단위 테스트라고 한다.)
✔️ 코드에 변경사항이 없다면 테스트는 항상 동일한 결과를 보장해야 한다. (외부 환경에 영향 🙅‍♀️)
✔️ 테스트 실행 순서에 영향을 받지 않는 테스트를 작성하자.
✔️ 테스트에서도 가능한 한 인터페이스를 사용해서 애플리케이션 코드와 느슨하게 연결해두는 편이 좋다.

🤔 테스트를 잘~ 하려면?

✔️ 테스트를 작성할 때엔 부정적인 케이스를 먼저 만드는 습관을 들이자. (예외적인 상황을 빠트리지 않는 꼼꼼한 개발이 가능하다.)
✔️ 테스트를 작성하고 성공시키는 코드를 만드는 작업의 주기를 가능한 한 짧게 가져가자
✔️ 스프링 컨테이너 없이 테스트할 수 있는 방법을 가장 우선적으로 고려하자.

junit 을 사용하자

junit은 프레임워크이다.
🙋‍♀️ junit을 사용하며 꼭 알아야할 것은! 테스트 메소드를 실행할 때마다 새로운 오브젝트를 생성한다는 것이다.
🤔 왜 일까?
💁‍♀️ junit 개발자는 각 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 확실히 보장해주기 위해 매번 새로운 오브젝트를 만들게 했다. 덕분에, 인스턴스 변수도 부담없이 사용할 수 있다. (다음 테스트 메소드가 실행될 때에는 새로운 오브젝트가 만들어져서 다 초기화 될 것!!)

UserDaoTest 개선

개선 전 UserDaoTest

public class UserDaoTest {	
    public static void main(String[] args) throws SQLException, ClassNotFoundException {	
        ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);	
        UserDao userDao = context.getBean("userDao", UserDao.class);	

        User user = new User();	
        user.setId("id");	
        user.setName("이름");	
        user.setPassword("password!@");	

        userDao.add(user);	

        System.out.println(user.getId() + " 등록 성공");	

        User user2 = userDao.get("dahyekim");	
        System.out.println(user2.getName());	
        System.out.println(user2.getPassword());	

        System.out.println(user2.getId() + " 조회 성공");	
    }	
}

👿 위의 코드의 문제점은 아래와 같다.
1. 사람의 눈으로 직접 확인하는 과정이 필요하다, 굉~장히 불편하다.
2. 매번 실행하는 것이 불편하다. DAO가 수백개가 된다고 생각해보자.

junit 전환

junit 전환해보자.
junit은 프레임워크다. 테스트를 만들 때, 유용하게 사용할 수 있다.

동일한 결과를 보장하는 테스트

어떤 경우에서도, 코드에 변경사항이 없다면 테스트는 항상 동일한 결과를 내야 한다.
일관성 있는 테스트

테스트 케이스 추가 & 예외조건에 대한 테스트

한 가지 결과만 검증하고 마는 것은 상당히 위험하다. (여러 조건을 추가하는 경우 실행 순서에 영향을 받지 않게 만들어야 한다.)
또한, 테스트 시 부정적인 케이스를 먼저 만드는 것이 좋다.
테스트 케이스 추가
예외조건에 대한 테스트 - id값에 해당하는 사용자 정보가 없는 경우

반복적인 코드 제거

반복적인 코드 제거
👿 junit에서는 테스트 메서드가 실행될 때마다 매번 테스트 클래스의 오브젝트를 새로 만든다는 것이다. 따라서, 위의 ApplicationContext도 세 번 만들어진다. (속도적, 리소스 적으로 좋지 않다😭)

junit 개발자는 각 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 확실히 보장해주기 위해 매번 새로운 오브젝트를 만들게 했다.

ApplicationContext 생성 방식 개선

위의 코드에서 테스트 별로 ApplicationContext가 매번 생성되기 때문에 시간과 자원이 소모되고 있다. Junit 프레임워크의 확장 클래스를 지정해주면 테스트가 사용할 ApplicationContext를 만들고 관리하는 작업을 진행해준다. (테스트가 실행하기 전에 딱 한 번만 ApplicationContext를 만들어두고, 공유해서 사용하도록 해준다.)
AppliactionContext 생성 방식 개선

@ExtendWith(SpringExtension.class)
@ContextConfiguration(locations = "/applicationContext.xml")

스프링 api에 의존하지 않는 테스트

UserDao는 DI가 적용되어 있기 때문에, 스프링의 API에 의존하지 않게 개선 가능하다. (+a, 테스트 시간이 절약된다 😀)
스프링 api에 의존하지 않는 테스트

학습 테스트

🤔 학습 테스트란?
자신이 사용할 API나 프레임워크의 기능을 테스트로 보면서 사용법을 익히는 것이다.
😇 학습 테스트의 장점?

  • 다양한 조건에 따른 기능을 손쉽게 확인해볼 수 있다.
  • 코드를 개발 중에 참고할 수 있다.
  • 프레임워크나 제품을 업그레이드할 때 호환성 검증을 도와준다.
  • 테스트 작성에 대한 좋은 훈련이 된다.
  • 새로운 기술을 공부하는 과정이 즐거워진다.

JUnit 테스트 오브젝트 테스트

JUnit은 테스트 메소드를 수행할 때마다 새로운 오브젝트를 만든다고 한다. 정말일까?

스프링 테스트 컨텍스트 테스트

JUnit과 반대로 스프링의 테스트용 어플리케이션 컨텍스트는 테스트 개수에 상관없이 한 개만 만들어진다. 정말일까?

JUnit5 참고

https://junit.org/junit5/docs/current/user-guide/
https://howtodoinjava.com/junit5/before-each-annotation-example/

0개의 댓글