본문 바로가기

스프링

AOP 트랜잭션기초2 고립된테스트 STUB MOCK 단위 통합테스트

1.     Com.springsource.javax.activation : Spring java-mail

2.     Com.springsource.javax.mail : Spring java-mail

3.     Com.springsource.junit : junit

4.     Commons-logging : Spring-context가 사용

5.     Mail : java-mail

6.     Mysql-connector : Mysql JDBC

7.     Org.springframework.context.support : Spring java-mail

8.     Spring-aop : 스프링 기능 자체의 aop

9.     Spring-bean : 스프링 빈을 활용하는 경우 필요. 스프링의 XML 설정파일과 자바 애노테이션을 파싱 하는데 필요한 클래스 포함

10.   Spring-context : 스프링 코어를 확장한 많은 클래스가 들어 있는데 모든 클래스는 EJB, JNDI(Java Naming Directory Interface), JMX용 클래스와 연동하는데 applicationcontext기능을 사용해야 하며 스프링 리모팅 클래스, 동적 스크립팅 언어(제이루비, 그루비등)와 연동하는 클래스, 빈 유효성검증(JSR-303) API, 스케줄링을 하는 클래스도 포함되어 있다.

11.   Spring-core : 모든 스프링 모듈에서 필요한 모듈. 다른 스프링 모듈에서 사용하는 공통 클래스가 포함됨.

12.   Spring-dao : EmpltyResultDataAccessException 등 사용을 위한 jar

13.   Spring-expression : 스프링 표현언어(SpEL) 지원 클래스 포함.

14.   Spring-jdbc : 스프링이 지원하는 jdbc.

15.   Spring-test.jar

-       @RunWith : Junit 프레임워크의 테스트 실행방법을 확장시 사용.

-       SpringJUnit4ClassRunner : 어플리케이션컨텍스트를 만들고 관리하는 확장 클래스

-       @ContextConfiguration(경로) : 자동으로 만들어줄 어플리케이션 컨텍스트 설정파일

16.   Spring-tx : DuplicateKeyException.class 파일 존재 및 스프링 트랜잭션

 

고립된 단위 테스트

테스트할 대상이 크고 복잡하면 테스트를 만들기도 그만큼 어렵고, 만들었다 해도 충분히지 못하다. 클래스 수십 개가 얽히고 설혀서 오류를 찾기 어려운 부분을 개선.

>  UserServiceTest가 테스트하고자 하는 대상은 UserService이다. 위 그림을 보면 Service 뒤에 존재하는 서비스, 서버, 심지어 네트워크까지 함께 테스트 하는 셈이다.

 

DB, 메일 등 여러가지가 아닌 고립된 테스트를 위해 목 오브젝트에 의존하도록 만들 수 있다.

 

 

레벨의 정보(다음레벨 정보까지 역할위임)

 

다음 레벨을 User객체에도 셋팅 역할위임

 

UserDao : Hibernate, JPA, JDO, JDBC 등 여러 액세스 기술일 수 있으므로 인터페이스 주입

 

 

JDBC DAO 구현

 

 

 

DataAccess API(Hibernate, JDBC, JDO, JPA) 등은 트랜잭션 방식이 다르므로 인터페이스 주입

 

 

 

트랜잭션 코드를 걷어내고 비즈니스 로직에만 충실

 

비즈니스 로직은 impl을 주입받아 그대로 사용하고 트랜잭션관련 로직만 추가시킴

 

 

아무것도 안하는 메일센더 구현. 매 테스트마다 메일발송을 하면 과부하(stub)

 

48. 고립된 테스트에서는 테스트 대상 오브젝트를 직접 생성. 기존 테스트에서는 컨테이너에서 가져온 UserServiceDI를 통해서 많은 의존 오브젝트와 서비스, 외부 환경에 의존하고 있었으므로, 완전히 고립돼서 테스트만을 위해 독립적으로 동작하는 테스트 대상을 사용할 것이기 때문에 새로 객체생성.(만약 upgradeLevels() 테스트만 있었다면 스프링 테스트 컨텍스트를 이용하기 위해 도입한 @RunWith 등은 제거할 수 있었다.)

49, 50. 목오브젝트로 만든 UserDao를 직접 DI

60. MockUserDao로부터 업데이트 시도한 List<User>를 가져와서 업데이트 대상과 비교함

 

> 기존에는 DB에서 가져와 일일이 확인해야 했지만 이제 그럴 필요없다.

 

85. 스텁(Stub) 기능 제공(getAll()) : 테스트를 위해 미리 준비한 응답만 제공하는 것. DB에서 가져온 것처럼 메모리에 List형태로 가지고 있다가 돌려주는 기능.

88. 목 오브젝트(Mock object, void update()) : 응답에 대한 확인 기능을 수행하는 역할. 업그레이드 대상 User 오브젝트를 저장해 뒀다가 검증을 위해 돌려주기 위한 기능.

91~94. 목 오브젝트에서 사용하지 않을 메소드는 실수로 사용될 위험이 있으므로, 위와같이 Exception을 던지도록 구현

 

고립된 테스트 장점

이것으로 테스트 수행 시간이 단축됨.

만약 DB에서 복잡한 방법으로 대량의 데이터를 조합해 가져오는 SQL, 혹은 수많은 DB 업데이트나 등록이 일어나는 테스트라면 수행시간은 훨씬 큰 차이를 보일 것이다.

테스트가 빨라지면 자주 테스트를 돌려볼 수 있고, UserService 수정하면서 다른 기능에 영향을 주지 않는지 확인해보고 싶다면 관련 있는 다른 테스트도 같이 실행해보면 된다.

목 오브젝트 작성과 같은 약간의 수고가 필요할지 모르겠으나, 그 보상은 충분함.

 

단위테스트 : 테스트 대상클래스(UserService)를 목오브젝트 등 테스트 대역을 이용해 의존 오브젝트나 외부의 리소스를 사용하지 않도록 고립시켜서 테스트 하는 것.

통합테스트

외부의 DB나 파일, 서비스 등의 리소스가 참여하는 테스트.

2개 이상의 단위가 결합해서 동작.

DI된 오브젝트를 테스트하는 것도 통합테스트.

>  DAO는 보통 통합테스트를 진행함. 물론 단위테스트를 쓸 때도 있음.