Lecture-05-3

Download Report

Transcript Lecture-05-3

5.4 메일 서비스의 추상화
1
5.4.0 새로운 요구사항 접수
 새로운 요구사항
– 레벨이 업그레이드 되는 사용자에게 안내 메일 발송
 새로운 요구사항 실현을 위한 변경 사항
– 사용자 이메일 정보 관리
• User에 email 필드 추가
• UserDao 수정
 userMapper 수정
 insert(), update()에 email 필드 처리 코드 추가
• UserServiceTest, UserDaoTest, UserTest 수정
– 업그레이드 작업을 담은 UserService의 upgradeLevel() 메소드에
메일 발송 기능 추가
5.4.1 JavaMail을 이용한 메일 발송 기능
 JavaMail 메일 발송
– upgradeLevel() 메소드 수정
5.4.1 JavaMail을 이용한 메일 발송 기능
 JavaMail 메일 발송
– javax.mail.JavaMail
클래스 사용
– sendUpgradeEmail()
메소드 추가
5.4.2 JavaMail이 포함된 코드의 테스트
 개발 중 JavaMail 관련 테스트시 고려점
– 개발 중 메일 서버가 부재한(올바르지 않은) 경우의 테스트 실패
– 개발 중 메일 서버가 올바르게 동작한다고 해도 매번 메일을 보내
는 것이 올바른가?
• 테스트 실행은 빈번하게 발생
 그 때 마다 메일 발송은 서버에 많은 부담
• 테스트시 수신자의 메일 주소는 올바른가?
– 괜찮은 해결책: 테스트용 메일 서버를 별도로 준비하여 사용
5.4.2 JavaMail이 포함된 코드의 테스트
 개발 중 JavaMail 관련 테스트시 고려점
– 다른 해결책: 테스트용 JavaMail을 사용
• 자바에서 제공하는 표준 JavaMail은 어느정도 그 기능이 검증된 클래스
• 기존 JavaMail 관련 클래스들과 인터페이스가 동일한 테스트용
JavaMail 클래스를 활용
• 장점
 매번 검증이 필요 없는 불필요한 메일 전송 요청을 보내지 않아도 됨
 테스트가 빠르고 안전하게 수행됨
5.4.3 테스트를 위한 서비스 추상화
 JavaMail을 이용한 테스트의 문제점
– JavaMail의 핵심 클래스: javax.mail.Session
– Session 클래스의 경직성
• Session은 인터페이스가 아니고 클래스
• 생성자가 private이라 직접 객체 생성 불가능
 스태틱 팩토리 메소드를 이용하여 객체
• Session 클래스는 상속이 불가능한 final 클래스
– MailMessage와 Transport 클래스도 마찬가지임
– JavaMail의 구현을 테스트용으로 바꿔치기가 거의 불가능
5.4.3 테스트를 위한 서비스 추상화
 스프링의 JavaMail 추상화
– 스프링은 java가 제공하는 JavaMail을 사용해 만든 코드가 테스트에
용이치 않은점을 인지하고 별도로 추상화 기능을 제공하고 있음
 스프링의 JavaMail 관련 클래스 및 코드
– MailSender/MailMessage 인터페이스
– SimpleMailMessage 클래스
5.4.3 테스트를 위한 서비스 추상화
 스프링의 JavaMail 관련 클래스 및 코드
– JavaMailSender 인터페이스와 JavaMailSenderImpl 클래스
• 지저분한 try/catch 블록이 사라짐
 MailException 런타임 예외 사용
5.4.3 테스트를 위한 서비스 추상화
 스프링의 JavaMail 관련 클래스 및 코드
– 스프링의 DI 적용
5.4.3 테스트를 위한 서비스 추상화
 스프링의 JavaMail 관련 클래스 및 코드
– 설정 파일 내의 빈 등록
– 현재까지는 기존 Java에서 제공하는 JavaMail API에서 스프링의
JavaMail API를 사용하도록 변경
• 메일 전송 기능을 인터페이스를 사용하여 추상화
• DI를 통한 구체적 클래스 완전 분리
• 테스트에 활용하기가 매우 용이
5.4.3 테스트를 위한 서비스 추상화
 테스트용 메일 발송 객체
– 테스트용 MailSender 클래스인 DummyMailSender 구현
• send() 메소드가 실제로 하는 일이 없음
• 콘솔에 메일 내용을 출력하는 정도로 업그레이드 가능
5.4.3 테스트를 위한 서비스 추상화
 테스트용 메일 발송 객체
– DummyMailSender 빈 등록
– UserServerTest 클래스에 테스트시 구현한 upgradeAllOrNothing()
메소드에도 mailSender 빈을 수동으로 주입
5.4.3 테스트를 위한 서비스 추상화
 테스트와 서비스 추상화
– 서비스 추상화
• 기능은 유사하나 사용 방법이 다른 로우레벨의 다양한 기술에 대해
추상 인터페이스와 일관성 있는 접근 방법을 제공해 주는 것
• 스프링의 JavaMail 서비스 추상화 사용
 JavaMail 의 구체적 기능이 변경되어도 클라이언트인 UserService는 전혀
수정할 필요가 없음
5.4.4 테스트 대역
 의존 객체의 변경을 통한 테스트 방법
– UserDaoTest는 UserDao의 동작을 테스트하기 위함
• 테스트시에는 SimpleDataSource를 사용하여 실제 운영하여
서버 활용을 못하게 막음
• 그럼에도 불구하고, 다음과 같은 단점 존재
 테스트 DB와의 연결
 SimpleDataSource 빈 생성 및 UserDao로의 DI 작업
• UserDao 테스트만을 목적으로 한다면 위의 간단한 작업들 모두
번거로운 짐이 됨
5.4.4 테스트 대역
 의존 객체의 변경을 통한 테스트 방법
– UserServiceTest는 UserService의 동작을 테스트하기 위함
• 테스트시에는 DummyMailServer를 사용하여 실제 메일 전송차단
• 이 경우 그 외 번거로운 작업은 없음
5.4.4 테스트 대역
 테스트 대상 객체의 의존성 문제
– UserService: 테스트 대상 객체
– UserService는 DI를 통해 주입받는 객체가 세가지임
• 즉, UserService는 이 세가지 객체에 의존적이 됨
– 문제점
• 간단하게 UserService만을 테스트하기 위하여 DI를 통하여 세가지
객체를 주입하는 거창한 작업이 뒤따름
 테스트 대역 (Test Double)
– 테스트 대상 객체가 사용하는 의존 객체들을 대체할 수 있도록
만든 객체
– 즉, 테스트 대상 객체가 원활하게 동작할 수 있도록 도우면서 테스
트를 위해 간접적인 정보를 제공해주기도 함
– 종류: 테스트 스텁 (Test Stub)과 목 객체 (Mock Object)
5.4.4 테스트 대역
 테스트 스텁 (Test Stub)
– 테스트 대상 객체의 의존객체로서 존재하면서 테스트 동안에 코드
가 정상적으로 수행할 수 있도록 돕는 객체
• 테스트 코드 내부에서만 간접적으로 사용
• 테스트시에 DI를 통하여 테스트 대상 객체에 주입함
• 예: DummyMailSender
– 테스트 스텁의 한계
• 테스트 대상 객체의 메소드가 돌려주는 결과뿐 아니라 의존 객체가
넘기는 값과 그 행위 자체에 대한 검증이 불가함
5.4.4 테스트 대역
 목 객체 (Mock Object)
– 테스트 대상 객체와 의존 객체 사이에서 일어나는 일을 검증할 수
있도록 특별히 설계된 객체
– 테스트 스텁처럼 테스트 객체가 정상적으로 실행되도록 도와주면
서 테스트 객체와 자신 사이에서 일어나는 내용을 저장해 두었다
가 테스트 결과를 검증하는 데 활용할 수 있도록 도와줌
– (1)~(4)까지는 테스트 스텁과 동일한 기능
– (5): 목 객체는 테스트 대상 객체와 자신 사이에 주고받는 정보를
보존하고 테스트에게 직접 그 정보를 제공한다.
5.4.4 테스트 대역
 목 객체를 이용한 테스트
– upgradeLevels() 테스트의 확장
• 메일 전송이 실제로 되었다는 점을 어느 정도 확인할 수 있도록 확장
• send() 메소드가 수행되면 수신자의 메일 주소를 저장
• 외부에서는 접근자 메소드 getRequest()를 통해 저장해둔 메일 주소
확인 가능
5.4.4 테스트 대역
 목 객체를 이용한 테스트
목 객체는 테스트 대상 객체의
내부에서 일어나는 일이나
자신과 함께 일어나는 일들에
대해 검증하게 해줌