홍팍 님의 스프링 부트, 입문! 강의를 보고 작성한 내용이며 이미지 또한 강의에 나오는 이미지를 따라 만들었습니다.
https://www.youtube.com/watch?v=Ym7cAtE2jQs&list=PLyebPLlVYXCiYdYaWRKgCqvnCFrLEANXt&index=29
Service : 처리 업무의 순서를 총괄
업무 처리는 transaction 단위로 수행
기존에 Controller가 Repository와 연동해서 수행하던 작업을 담당
Controller : 클라이언트로부터 요청을 전달받아서 Service에게 전달
Service : 전달받아서 정해진 작업 순서에 따라 작업 수행, 트랜잭션 관리
Repository : DB와 연동하여 작업을 수행 (Service내에 Repository 객체 존재)
Transaction
모두 성공되어야 하는 일련의 과정을 의미
transaction은 service가 관리
@Transactional
: 해당 메소드를 트랜잭션으로 묶는다, 수행 중에 실패하면 해당 메소드가 수행되기 이전 상태로 rollback
기본패키지/service 내에 클래스 생성
@Service
: 해당 클래스를 서비스로 인식하여 스프링 부트에 객체를 생성(등록)
Repository를 통해 DB와 연동을 위해 클래스 내에 Repository 객체 생성
Controller에서 service 객체 생성 시 @Autowired
사용
기존 코드 수정사항
이전에 입력된 return 문을 service의 메소드를 호출하도록 변경
return 문에서 수행하던 일을 service의 메소드에서 수행되도록 작성
stream : 자바의 컬렉션이나 배열의 원소에 대한 작업 수행 시, for 문이 아닌 stream을 이용하여 람다함수형식으로 작성 가능
map : 항목들을 함수 결과에 해당하는 값으로 매핑
collect : stream 데이터를 원하는 자료형으로 변경
<ArticleApiController>
// 트랜잭션 테스트
// 트랜잭션 -> 실패 -> rollback
@PostMapping("/api/transaction-test")
public ResponseEntity<List<Article>> transactionTest(@RequestBody List<ArticleForm> dtos) {
List<Article> createdList= articleService.createArticles(dtos);
return (createdList != null) ?
ResponseEntity.status(HttpStatus.OK).body(createdList) :
ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
<ArticleService>
// 트랜잭션 테스트
@Transactional // 해당 메소드를 트랜잭션으로 묶는다
public List<Article> createArticles(List<ArticleForm> dtos) {
// dto 묶음을 entity 묶음으로 변환
// dtos의 항목들을 하나씩 Entity로 변환
List<Article> articleList = dtos.stream().map(dto -> dto.toEntity()).collect(Collectors.toList());
// entity 묶음을 DB에 저장
// articleList를 반복하면서 하나씩 저장
articleList.stream().forEach(article -> articleRepository.save(article));
// 강제 예외 발생
articleRepository.findById(-1L).orElseThrow(() -> new IllegalArgumentException("결재 실패!"));
// 결과값 반환
return articleList;
}
프로그램의 품질 검증을 위한 것
원하는대로 프로그램이 동작하는지 확인하는 것
예상 시나리오 작성, 실제 코드 결과와 비교하여 검증
테스트 통과 시, refactoring
실패 시, debuging
성공하는 경우와 실패하는 경우에 대해서도 여러 케이스가 존재
TDD : Test Driven Development
@SpringBootTest
: 스프링부트와 연동한 통합 테스트 수행 (해당 클래스는 스프링부트와 연동되어 테스팅된다 )
@Test
: 해당 메소드가 test를 위한 코드임을 선언
Test 수행 메소드 우클릭 -> Generate -> Test
service에 대해 test를 진행하려고 하니까 service 객체를 Autowired를 통해 생성
예상 코드 / 실제 코드 / 비교 코드로 메소드를 작성한다
실제코드 : 직접 함수를 호출
비교코드 : 결과(반환값)이 동일한지 비교
assertEquals(기댓값, 실제값)
테스트에 @Transactional
추가
테스트 종료 후 변경된 데이터를 롤백 처리
데이터가 생성, 변경, 삭제되는 경우, 이와 같은 처리를 해야 전체 테스트가 성공적으로 수행됨
테스트 코드의 경우, 테스트 성공 후 롤백됨