Spring Projcect/[팀플] In & Out 가계부

회원 아이디 & 비밀번호 찾기

계란💕 2022. 10. 19. 18:40

아이디(email) 찾기 & 비밀번호 찾기

  • API
    • 이메일: api/password/email
    • 비밀번호: api/password/email/phone
  • email을 입력받아서 존재하는 아이디인지 확인한다.

 

 

  • 새로운 Input 클래스를 만든다.
    • 컨트롤러에서 @RequsetBody를 적용하기 위해서 만든다.
<hide/>
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FindPasswordMemberInput {
    private String email;
    private String phone;
}

 

 

  • Impl 클래스
    • findMemberByEmail() 메서드를 findEmail(), findPhone() 에 모두 적용한다.
<hide/>
private Member findMemberByEmail(String email) {
    Optional<Member> optionalMember = memberRepository.findByEmail(email);
    if (!optionalMember.isPresent()) {
        throw new RuntimeException("존재하지 않는 아이디(이메일)입니다. 이메일을 정확하게 입력해주세요");
    }
    return optionalMember.get();
}

@Override
public String findEmail(String email) {
    findMemberByEmail(email);
    return email;
}

@Override
public String findPhone(String email, String phone) {

    Member optionalMember = findMemberByEmail(email);
    if (!optionalMember.getPhone().equals(phone)) {
        throw new RuntimeException("올바른 연락처(번호)가 아닙니다. 다시 입력해주세요");
    }
    return optionalMember.getPhone();
}

 

 

  • ctrl
    • @RequestBody를 이용하면 입력받는 인풋 클래스를 컨트롤러 매서드의 매개 변수로 넣어서 적용할 수 있다.
<hide/>
@PostMapping("/password/email")
public ResponseEntity<?> checkEmail(
    @RequestBody FindPasswordMemberInput findPasswordMemberInput) {

    String findEmail = memberService.findEmail(findPasswordMemberInput.getEmail());
    return new ResponseEntity(findEmail, HttpStatus.OK);
}

@PostMapping("/password/email/phone")
public ResponseEntity<?> checkPhone(
    @RequestBody FindPasswordMemberInput findPasswordMemberInput) {

    String findPhone = memberService.findPhone(findPasswordMemberInput.getEmail(),
        findPasswordMemberInput.getPhone());
    return new ResponseEntity(findPhone, HttpStatus.OK);
}

 

 

 

  Ex) API 테스트

 

 

 

  • test 클래스
    • 이메일 찾기
    • anyString()은 어떤 값을 넣어도 상관없는건가?
    • 멤버를 만들어서 findByEmail()을 했을 때, member 객체를 반환할 것이다. 라고 조건을 준다.?
    • 이메일 찾기니까 email을 설정해서 
<hide/>

@Test
@DisplayName("아이디 찾기 - 이메일 확인")
void findEmail() {

    // given
    Member member = Member.builder()
        .email("egg@naver.com")
        .address("서울특별시")
        .phone("010-2222-0000")
        .birth(LocalDate.from(LocalDate.of(2000, 9, 30)))
        .gender("남")
        .nickName("원빈")
        .password("abc!@#12")
        .build();
   // 삭제 memberRepository.save(member);

    given(memberRepository.findByEmail(anyString())).willReturn(Optional.of(member));
    // 만든 멤버를 반환한다고 가정한다.

    // when
    String email = "egg@naver.com";
    String findEmail =  memberService.findEmail(email);

    // then
    Assertions.assertEquals(email, findEmail);
}

@Test
@DisplayName("비밀번호 찾기 - 이메일, 휴대폰 일치 확인")
void findPhone() {

    // GIVEN
    Member member = Member.builder()
        .email("egg@naver.com")
        .address("서울특별시")
        .phone("010-2222-0000")
        .birth(LocalDate.from(LocalDate.of(2000, 9, 30)))
        .gender("남")
        .nickName("강동원")
        .password("abc!@#12")
        .build();

    given(memberRepository.findByEmail(anyString())).willReturn(Optional.of(member));

    // WHEN
    String email = "egg@naver.com";
    String phone = "010-2222-0000";
    String findPhone = memberService.findPhone(email, phone);


    //THEN
    Assertions.assertEquals(findPhone, phone);
}

 

 

 

  • 컨트롤러 테스트
    • ArgumentCaptor<> 
      • capture했을 때의 결과가 join은 JoinMemberInput?
      • findEmail(), findPhone()의 반환형은 String이고 join() 의 반환형은 void 라서 그런가?
      • findPhone() 할 때는 이메일을 anyString()으로 바꾼다.
<hide/>
@WebMvcTest(MemberController.class)
@DisplayName("MemberController 테스트")
@AutoConfigureMockMvc(addFilters = false)
class MemberControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired
    ObjectMapper mapper;

    @MockBean
    private MemberServiceImpl memberServiceImpl;

    @MockBean
    private MemberRepository memberRepository;

    @Test
    void signUp() throws Exception {

        // given
        JoinMemberInput memberInput = JoinMemberInput.builder()
            .email("egg@naver.com")
            .address("서울특별시")
            .phone("010-2222-0000")
            .birth(LocalDate.from(LocalDate.of(2000, 9, 30)))
            .gender("남")
            .nickName("원빈")
            .password("1")
            .build();
        String memberInputJson = mapper.writeValueAsString(memberInput);

        //when
        mockMvc.perform(
                post("/api/signup")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(memberInputJson))
            .andExpect(status().isOk())
            .andDo(print());
        ArgumentCaptor<JoinMemberInput> captor = ArgumentCaptor.forClass(JoinMemberInput.class);

        //then
        Mockito.verify(memberServiceImpl, times(1)).join(captor.capture());
        assertEquals(captor.getValue().getEmail(), memberInput.getEmail());

    }

    @Test
    void checkEmail() throws Exception {

        // given
        FindPasswordMemberInput memberInput = FindPasswordMemberInput.builder()
            .email("egg@naver.com")
            .build();
        String inputToJson = mapper.writeValueAsString(memberInput);

        // when
        mockMvc.perform(
                post("/api/password/email")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(inputToJson))
            .andExpect(status().isOk())
            .andDo(print());

        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

        // then
        Mockito.verify(memberServiceImpl, times(1)).findEmail(captor.capture());
        assertEquals(captor.getValue(), memberInput.getEmail());
    }

    @Test
    void checkPhone() throws Exception {

        // given
        FindPasswordMemberInput memberInput = FindPasswordMemberInput.builder()
            .email("egg@naver.com")
            .phone("010-2345-1234")
            .build();
        String inputToJson = mapper.writeValueAsString(memberInput);

        //when
        mockMvc.perform(
                post("/api/password/email/phone")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(inputToJson))
            .andExpect(status().isOk())
            .andDo(print());
        ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);

        //then
        Mockito.verify(memberServiceImpl, times(1)).findPhone(anyString(), captor.capture());
        assertEquals(captor.getValue(), memberInput.getPhone());
    }
}

 

 

 

 

궁금한 점

  • @RequestParam, @RequestBody 차이점은?
    • 둘다 컨트롤러의 매개변수에 주는 어노테이션이다.
    • @RequestParam은 url에 매개변수명이 노출된다.  각 변수별로 데이터를 저장 가능하다. 객체 생성 불가능
    • @RequestBody는 별도의 Input 클래스를 만들어서 사용할 수 있다. 객체 생성이 가능하다. 변수변로 데이터 저장이 불가능하다.
  • ArgumentCaptor<>란?
    • 매개 변수(parameter)에 실제 넣는 값을 argument라고 한다.
    • 특정 메서드에 사용되는 argument(인자)를 capture(저장)했다가 나중에 다시 getValue() 해서 사용 가능하다.

'Spring Projcect > [팀플] In & Out 가계부' 카테고리의 다른 글

회원 가입 API  (0) 2022.10.27
회원 로그아웃 API  (0) 2022.10.26
회원 예외 처리 MemberErrorCode, ExceptionHandler  (0) 2022.10.25
회원 로그인 API  (0) 2022.10.25
회원 정보 조회 및 수정 API  (0) 2022.10.21