💡 .java를 클릭시 관련 커밋으로 이동💡
회고
@ApiResponse(responseCode = "200", description = "컨벤션 등록 성공")
@PostMapping("/")
public JsonResult<?> registerStudyConvention(@AuthenticationPrincipal User user,
@RequestParam(name = "studyInfoId") Long studyInfoId,
StudyConventionController 에서 studyInfoId 를 @RequestParam 어노테이션 즉, 쿼리 파라미터로 처리를 했었지만 쿼리 파라미터는 주로 filter값이나 pagination에 필요한 정보(cursorIdx, limit등) 비교적 간단한 정보를 전달하는 데 적합하다는 것을 깨달았다!!
⏬ 변경
StudyConventionController.java
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/convention")
public class StudyConventionController {
private final StudyConventionService studyConventionService;
private final StudyMemberService studyMemberService;
@ApiResponse(responseCode = "200", description = "컨벤션 등록 성공")
@PostMapping("/")
public JsonResult<?> registerStudyConvention(@AuthenticationPrincipal User user,
@Valid @RequestBody StudyConventionRequest studyConventionRequest) {
studyMemberService.isValidateStudyLeader(user, studyConventionRequest.getStudyInfoId());
studyConventionService.registerStudyConvention(studyConventionRequest);
return JsonResult.successOf("StudyConvention register Success");
}
}
@RequestBody 를 사용하여 DTO에 studyInfoId를 넣어주었다 ⇒ 사용자가 직접 입력하는 방식이 아닌 프론트에서 등록한 값에 studyInfoId를 추가하여 넣어줄 예정
나중에 다시 @PathValiable 로 변경하여 studyInfoId를 받아주었다. ㅎㅎ,, 그이유는
Todo api 구현할때 그렇게 사용하기도 했고 (통일성) + 컨벤션 삭제 api 구현하면서 url에 혼동이 올수도 있겠다 싶어서 변경하게되었..
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class StudyConventionRequest {
private Long studyInfoId; // 스터디 Id
@NotBlank(message = "컨벤션 이름은 공백일 수 없습니다.")
@Size(max = 20, message = "이름 20자 이내")
private String name; // 컨벤션 이름
@Size(max = 50, message = "설명 50자 이내")
private String description; // 컨벤션 설명
@NotBlank(message = "컨벤션 내용은 공백일 수 없습니다.")
@Size(max = 40, message = "내용 40자 이내")
private String content; // 컨벤션 내용(정규식)
@Builder.Default
private boolean active = true; // 컨벤션 적용 여부
}
Dto 추가
@Slf4j
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class StudyConventionService {
private final StudyConventionRepository studyConventionRepository;
// 컨벤션 등록
@Transactional
public void registerStudyConvention(StudyConventionRequest request) {
// 컨벤션 저장
studyConventionRepository.save(StudyConvention.builder()
.studyInfoId(request.getStudyInfoId())
.name(request.getName())
.description(request.getDescription())
.content(request.getContent())
.isActive(request.isActive())
.build());
}
}
Convention 등록 Service 구현
테스트
public class StudyConventionFixture {
// 테스트용 컨벤션 등록
public static StudyConventionRequest generateStudyConventionRequest(Long studyInfoId) {
return StudyConventionRequest.builder()
.studyInfoId(studyInfoId)
.name("컨벤션")
.description("설명")
.content("정규식")
.active(true)
.build();
}
}
컨벤션 등록을 위한 Convention Fixture 작성
StudyConventionControllerTest.java
@Test
public void Convetion_등록_테스트() throws Exception {
//given
User savedUser = userRepository.save(generateAuthUser());
Map<String, String> map = TokenUtil.createTokenMap(savedUser);
String accessToken = jwtService.generateAccessToken(map, savedUser);
String refreshToken = jwtService.generateRefreshToken(map, savedUser);
StudyInfo studyInfo = StudyInfoFixture.createDefaultPublicStudyInfo(savedUser.getId());
studyInfoRepository.save(studyInfo);
StudyConventionRequest request = StudyConventionFixture.generateStudyConventionRequest(studyInfo.getId());
doNothing().when(studyMemberService).isValidateStudyLeader(any(User.class), any(Long.class));
doNothing().when(studyConventionService).registerStudyConvention(any(StudyConventionRequest.class));
//when , then
mockMvc.perform(post("/convention/")
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, createAuthorizationHeader(accessToken, refreshToken))
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.res_code").value(200))
.andExpect(jsonPath("$.res_msg").value("OK"))
.andExpect(jsonPath("$.res_obj").value("StudyConvention register Success"))
.andDo(print());
}
@Test
public void Convention_등록_유효성_검증_실패_테스트() throws Exception {
//given
String inValidName = " ";
String expectedError = "name: 컨벤션 이름은 공백일 수 없습니다.";
User savedUser = userRepository.save(generateAuthUser());
Map<String, String> map = TokenUtil.createTokenMap(savedUser);
String accessToken = jwtService.generateAccessToken(map, savedUser);
String refreshToken = jwtService.generateRefreshToken(map, savedUser);
//when , then
mockMvc.perform(post("/convention/")
.contentType(MediaType.APPLICATION_JSON)
.header(AUTHORIZATION, createAuthorizationHeader(accessToken, refreshToken))
.content(objectMapper.writeValueAsString(StudyConventionRequest.builder()
.name(inValidName)
.content("정규식")
.build())))
.andExpect(status().isOk())
.andExpect(jsonPath("$.res_code").value(400))
.andExpect(jsonPath("$.res_msg").value(expectedError))
.andDo(print());
}
컨트롤러 동작 검증 ( HTTP 요청을 올바르게 처리하고 적절한 응답을 반환하는지 확인)
Convention 등록을 성공했을때 → Convetion_등록_테스트()
Convention 등록을 실패했을때 (유효성 검증) → Convention_등록_유효성_검증_실패_테스트()
으로 나누어 테스트했다.
유효성 검증으로는 @NotBlank 공백일 경우 → 예외(실패)를 터트리는지 확인
StudyConventionServiceTest.java
@Test
@DisplayName("컨벤션 등록 테스트")
public void registerConvention() {
//given
User savedUser = userRepository.save(generateAuthUser());
StudyInfo studyInfo = StudyInfoFixture.createDefaultPublicStudyInfo(savedUser.getId());
studyInfoRepository.save(studyInfo);
StudyMember leader = StudyMemberFixture.createStudyMemberLeader(savedUser.getId(), studyInfo.getId());
studyMemberRepository.save(leader);
StudyConventionRequest request = StudyConventionFixture.generateStudyConventionRequest(studyInfo.getId());
//when
studyMemberService.isValidateStudyLeader(savedUser, studyInfo.getId());
studyConventionService.registerStudyConvention(request);
StudyConvention findConvention = studyConventionRepository.findByStudyInfoId(studyInfo.getId());
//then
assertEquals("컨벤션", findConvention.getName());
assertEquals("설명", findConvention.getDescription());
assertEquals("정규식", findConvention.getContent());
}
ConventionService 등록 테스트
'Project > 깃터디 (gitudy)' 카테고리의 다른 글
[깃터디/Convention] 컨벤션 수정 api 구현 (0) | 2024.05.11 |
---|---|
[깃터디/Convention] 컨벤션 조회 api 구현 (1) | 2024.05.11 |
[깃터디/Member] 스터디에 속한 스터디원 조회 api 구현 (0) | 2024.05.11 |
[깃터디/Member] 스터디 가입 신청 목록 조회 api 구현 (0) | 2024.05.11 |
[깃터디/Member] 스터디원 강퇴, 스터디원 탈퇴 api 구현 (0) | 2024.05.11 |
댓글