-
[Spring Boot] 팀 생성, DB 슬라이스 테스트Backend/개발 2021. 8. 5. 01:49반응형
TIL 36일차 개인프로젝트
오늘은 할 수 있던 시간 대비 공부한내용이나 구현한게 별로 많지 않다.. 많이 쉬었다..ㅠ_ㅠ
이렇게 쪼금씩쪼금씩 하면 거의 글 50개써야 겨우 완성될 것 같은데,, 사실 그래서 TIL 카테고리에 넣은거니까,,ㅎ 나중에 블로그용으로 쓰게되면 공부한거랑 구현한거 분리해서 다시 정리해야될 것 같다다ㅏㅏ...
DB에 값 넣기
일단 DB에 참가자가 등록 된 후의 구현을 먼저 해야할 것 같아서 넣어줬다. 총 20명
다음 순서로 진행된다.
- 일괄적으로 특정 라인의 참가자를 모두 불러와 팀에 등록하며 leader로 만들어준다.
- 이때 등록되는 참가자는 point가 존재하지 않는다(팀장이므로)
- 이때 팀이 순서대로 생성된다.
- 경매가 진행된다
- 특정 참가자가 랜덤으로 추출된다
- 채팅을 통해서 경매가 진행되고 타이머가 끝나면 낙찰된다
- 유찰의 경우 point에 체크해준뒤 종료된다.
- 경매 성공한 팀 / 낙찰된 참가자가 있다
- 팀에 참가자를 등록하고 경매 포인트만큼 차감한다.
- 참가자에 팀을 등록한다.
2-3을 반복한다.
- 동일 포지션에서 1명을 제외한 나머지 참가자가 팀이 결정되면 나머지는 자동으로 결정된다. (유찰이 된 참가자도 포함)
- 모든 참가자가 종료되고, 유찰된 참가자만이 모인다.
팀 생성
미드라이너를 팀장으로 팀을 생성해보았다.
@Transactional public void setTeamLeaderByPosition(String position){ List<ParticipantsEntity> participants = participantsRepository.findParticipantsEntitiesByMainPosition(position); for(ParticipantsEntity entity: participants){ entity.updatePoint(0l); TeamsEntity teamsEntity = TeamsEntity.builder() .teamName(entity.getSummonerName()+"팀") .leaderId(entity.getId()) .build(); teamsEntity.addParticipants(entity); teamsRepository.save(teamsEntity); } }
@Test public void 팀생성(){ // given String position = "MID"; // when teamsService.setTeamLeaderByPosition(position); // then List<TeamsEntity> teamsEntities = teamsRepository.findAll(); assertThat(teamsEntities.size()).isEqualTo(4); } //BUILD SUCCESSFUL in 14s //4 actionable tasks: 3 executed, 1 up-to-date //11:26:10 오후: Task execution finished ':test --tests "com.project.auction.lol.service.TeamsServiceTest.팀생성"'.
참가자와 팀이 연결되고, point를 0으로 지정해주었다.
나중에는 이걸 API로 만들어서 처리해주면 좋을 것 같아서 컨트롤러도 작성해보았다.
@GetMapping("/teams/leader/{position}") public ResponseEntity setTeamLeaderByPosition(@PathVariable String position){ String reg = "TOP|JUG|MID|ADC|SUP"; position = position.toUpperCase(); if(!Pattern.matches(reg, position)) return new ResponseEntity(HttpStatus.BAD_REQUEST); try { teamsService.setTeamLeaderByPosition(position); return new ResponseEntity(HttpStatus.OK); } catch (Exception e){ String message = "이미 팀이 생성되었습니다."; return new ResponseEntity(message, HttpStatus.CONFLICT); } }
- 올바르지 않은 포지션이 입력으로 들어왔을 경우 bad_request, 이미 팀이 만들어진 상태일 경우 conflict로 에러를 처리하였다.
Pattern.matches(정규식, 검색할문자)
는 boolean을 반환한다.- 테스트 코드를 작성 할 때는
@WebMvcTest(controllers = TeamsController.class)
를 사용해서 테스트의 범위를 service등이 아닌 controller로만 제한해주었다.
몇가지 예외처리를 controllerTest에서 webmvctest로 테스트해봤는데 안먹는거 보니, service단에서 throw를 날렸을 경우 controller에서 잡지 못했다. 실제로 어플리케이션을 돌리면 되는데 테스트코드에서 안되는 이유가 있을 것 같은데 찾지 못했다. ㅠ
보통 컨트롤러 내부에서 발생한 execption을 따로 처리하지 않고 바깥으로 내보내서 전역적으로 예외처리를 해주는 것 같다. 예외처리 할 일이 많아지면 한번에 해줘야겠다. 또 미루기..^^;ㅠ
MockMvc
테스트에 필요한 기능만 가지는 가짜 객체를 만들어 서버에 배포하지 않고 스프링 MVC 동작을 재현할 수 있는 클래스이다.
MockMvc method
perform()
- 요청을 전송하는 역할
- 결과로 ResultActions객체를 받으며 리턴값을 검증하고 확인할 수 있는 andExpect를 제공한다.
andExpect()
- 응답을 검증하는 역할
- 상태코드
status()
- 뷰, 리다이렉트, 모델정보, 응답정보
andDo(print())
- 요청/응답 전체메세지 확인
JpaMappingContext error
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: JPA metamodel must not be empty!
테스트를 하려고하는데 다음과같은 에러가 발생했다.
Auditing은 ParticipantsEntity에 BaseTimeEntity auditing 설정을 한 부분이 있었는데, 거기서 에러가 난 것 같다. 해당 기능을 사용하기 위해 Application 파일에 @EnableJpaAuditing 어노테이션으 설정해 주었는데, webmvctest같은 슬라이스 테스트에서는 해당 bean을 로드하지 않기 때문에 생긴 오류라고 한다.
@MockBean(JpaMetamodeMappingContext.class)
를 추가하여 해결해주었다. 따로 configuration을 분리하는 방법 도 있는데, 나중에 슬라이스 테스트 클래스가 많아질 경우 처리해주면 될 것 같다.
슬라이스 테스트
레이어 별로 잘라서 하는 단위테스트이다.
예를들어 MockMvc를 이용해 controller만을 테스트 할 때 Controller가 사용할 Service를 Mock함으로써(가짜 빈으로) 데이터 레이어와 상관 없이 컨트롤러의 동작이나 유효성만을 검사할 수 있다.
슬라이스 테스트를 하는 이유
@SpringBootTest
어노테이션의 단점- 모든 Bean을 로드하기 때문에 시간이 오래거린다.
- 테스트의 단위가 커서 테스트코드를 통한 빠른 피드백의 장점이 희석된다.
슬라이스 테스트 종류
@WebMvcTest
@Controller
,@ControllerAdvice
,@JsonComponent
,@WebMvcConfigurer
등만 Bean으로 등록한다. ( service, repository는 bean으로 등록하지 않음 )- 보통
@Autowired MockMvc
@MockBean xxxService
처리를 해준다. xxxService는 해당 컨트롤러에서 사용하는 서비스
@WebFluxTest
@DataJpaTest
- etc..
// 이미 팀이 생성되었다면 if(!teamsRepository.findAll().isEmpty()) throw new Exception();
service에 예외처리를 더 해주었다.
다 불러와야하는게 좀 별로긴한데.. count를 해도 더 복잡한 쿼리가 나갈 것 같고,, queryDsl에서 selectOne이나, query를 직접 작성해서
select 1
limit1 을 하면 되는 것 같다. - 참고 jojoldu- JPA exists 쿼리 성능 개선그런데 JPQL에선 limit을 지원하지 않는 것 같다. queryDsl을 사용할 때 수정해주어야 겠다.
출처
'Backend > 개발' 카테고리의 다른 글
[Spring Boot] 우승멤버 등록, controller 테스트 코드 작성하기 1 (0) 2021.08.12 [Spring Boot] 우승 멤버 별표표시 , @ElementCollection (2) 2021.08.05 [Spring Boot] mysql 연동 , DB 연관관계 고민 (0) 2021.08.04 [Spring Boot] JPA (4) 2021.08.03 [Spring Boot] 프로젝트 gradle 버전 변경 , h2 (2) 2021.08.03 - 일괄적으로 특정 라인의 참가자를 모두 불러와 팀에 등록하며 leader로 만들어준다.