완성보다 하나라도 배우는 것이 목표인 2*3 ==6 조!
- 팀원 소개/역할
김민수 - 댓글 좋아요 기능 구현 / 시큐리티
박상훈 - 게시글 좋아요 / 시큐리티
손혜은 - Comment CRUD 구현
이재원 - User CRUD 구현
장현재 - Board CRUD 구현
09:00 : 간단히 진행사항과 당일 목표/계획 공유
15:00 : 목표치 달성도 & 문제점 공유
개인이 맡은 기능에 대해 충분한 고민과 검색 후 안 되면 팀에 문제점 공유하기((max 1H)
→ 정해진 시간이 아니더라도 해결이 안 되는 문제는 바로 공유!!
깃 커밋시 알려주기
User / Board / Comment 기본 CRUD API에 JWT를 사용할 수 있도록 추가
Like 부분에 대한 작성 및 기능간의 테스트 실행
시큐리티 적용을 위해 해당 개념 학습
프로젝트 내에 시큐리티 적용
@Mock
LikeCommentRepository likeCommentRepository;
@Mock
CommentRepository commentRepository;
@Mock
UserRepository userRepository;
@InjectMocks // 가짜 객체 삽입,
LikeCommentService likeCommentService;
@Test
@DisplayName("좋아요 성공 케이스")
void clickFavorite() throws Exception {
//given
User user = mock(User.class);
Comment comment = mock(Comment.class);
when(user.getUsername()).thenReturn("userA");
when(comment.getId()).thenReturn(1L);
when(userRepository.findByUsername(user.getUsername())).thenReturn(Optional.of(user));
when(commentRepository.findById(comment.getId())).thenReturn(Optional.of(comment));
when(likeCommentRepository.existsByUserAndComment(user, comment)).thenReturn(false);
//when
String s = likeCommentService.clickFavorite(comment.getId(), user.getUsername());
//then
Assertions.assertSame("좋아요를 누르셨습니다",s);
}
@DisplayName("좋아요 실패 케이스")
@Test
void clickFavoriteError() throws Exception {
//given
User user = mock(User.class);
Comment comment = mock(Comment.class);
when(user.getUsername()).thenReturn("userA");
when(comment.getId()).thenReturn(1L);
when(userRepository.findByUsername(user.getUsername())).thenReturn(Optional.of(user));
when(commentRepository.findById(comment.getId())).thenReturn(Optional.of(comment));
when(likeCommentRepository.existsByUserAndComment(user, comment)).thenReturn(true);
//when / then
Assertions.assertThrows(Exception.class,()->likeCommentService.clickFavorite(comment.getId(), user.getUsername()));
}
@Test
@DisplayName("좋아요 취소 성공 케이스")
void cancelFavorite() throws Exception {
//given
User user = mock(User.class);
Comment comment = mock(Comment.class);
LikeComment likeComment = mock(LikeComment.class);
when(user.getUsername()).thenReturn("user1");
when(comment.getId()).thenReturn(1L);
when(userRepository.findByUsername(user.getUsername())).thenReturn(Optional.of(user));
when(commentRepository.findById(comment.getId())).thenReturn(Optional.of(comment));
when(likeCommentRepository.existsByUserAndComment(user, comment)).thenReturn(true);
//when
String s = likeCommentService.cancelFavorite(comment.getId(), user.getUsername());
//then
Assertions.assertSame("좋아요를 취소하였습니다", s);
}
@Test
@DisplayName("좋아요 취소 실패 케이스")
void cancelFavoriteException() throws Exception {
//given
User user = mock(User.class);
Comment comment = mock(Comment.class);
LikeComment likeComment = mock(LikeComment.class);
when(user.getUsername()).thenReturn("user1");
when(comment.getId()).thenReturn(1L);
when(userRepository.findByUsername(user.getUsername())).thenReturn(Optional.of(user));
when(commentRepository.findById(comment.getId())).thenReturn(Optional.of(comment));
when(likeCommentRepository.existsByUserAndComment(user, comment)).thenReturn(false);
//when //then
Assertions.assertThrows(Exception.class,()->likeCommentService.cancelFavorite(comment.getId(), user.getUsername()));
}
}
빌더 패턴
ResponseEntity를 return 타입으로 사용하던 중 형식이 조금씩 다른 문제점에 직면
ex) 1. return new ResponseEntity<>(body,status)
→ 생성자 / 빌더패턴의 차이
→ 만약 파라미터의 갯수의 변화가 빈번하거나, 여러 케이스가 필요하다 → 그만큼 생성자가 여러 종류여야함..
→ 빌더패턴 사용 → 유연한 생성자
→ Lombok Builder지원! → 다음 프로젝트에는 꼭 써보자!
Spring Security PermitAll()
처음 시큐리티의 흐름을 이해했을 때, permitAll()로 인증/인가를 풀어주게 되면 Filter를 아예 거치지 않는 줄 알았다. 하지만 결과적으로 우리가 커스텀해서 addBefore해준 필터를 거치게 되었고, 예기치 못한 Exception이 발생했다.
아직 정확한 개념은 모르지만 web.ignoring()으로 특정 URL요청에 필터를 거치지 않게 세팅했다.
설계에 시간을 충분히 들였다고 생각했지만, 더 세세하게 짜야 한다는 것을 알게 됐습니다. 또한 실력은 다 다르지만 팀장님을 중심으로 좋은 사람들이 모여 서로를 믿고 배려하면서 진행했습니다. 소통하고 화기애애한 분위기에 속에 프로젝트를 진행할 수 있었습니다. 또한 프로젝트를 통해 팀원 모두가 적어도 하나씩 새로 배우고, 부족했던 부분은 채울 수 있는 시간이 된 것 같습니다.