-
카테고리
-
해결 여부
미해결
스프링부트 단위테스트 어떻게 작성해야하는지 감이 안잡혀요.. 코드 리뷰 부탁립니다.
24.05.07 18:14 작성 조회수 52
0
안녕하세요. 단위테스트라는 것을 처음 작성해보는데 어떻게 작성해야할지 감이 안잡히네요 ㅠㅠ
일단 꾸역꾸역 작성을 해봤는데 이렇게 하는 게 맞는지 의문입니다. 너무 구체적으로 작성한 것은 아닌 지 고칠 부분이 있다면 피드백 해주시면 정말 감사하겠습니다.
아래 코드는 아이디, 이메일 중복 체크 및 레디스에 저장 된 인증번호를 체크한 후 회원가입을 구현한 코드입니다.
@Service
@Transactional
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
private final RedisService redisService;
@Override
public Member signUp(MemberRequest memberRequest) {
// 회원가입 조건 검증
verifySignUpCondition(memberRequest);
Member member = memberRequest.toEntity();
member.setPassword(passwordEncoder.encode(memberRequest.getPassword()));
member.setRole(Role.MEMBER);
member.setSns(Sns.NONE);
memberRepository.save(member);
// 회원가입 성공 시 레디스에서 관련 데이터 삭제
redisService.deleteKey(memberRequest.getEmail());
return member;
}
private void verifySignUpCondition(MemberRequest memberRequest) {
checkLoginIdDuplicate(memberRequest.getLoginId());
checkEmailDuplicate(memberRequest.getEmail());
redisService.verifyAuthNum(memberRequest.getEmail(), memberRequest.getAuthNum());
}
private void checkLoginIdDuplicate(String loginId) {
Optional<Member> findMember = memberRepository.findByLoginId(loginId);
if(findMember.isPresent()) {
throw new BusinessException(ErrorCode.LOGIN_ID_DUPLICATE);
}
}
private void checkEmailDuplicate(String email) {
Optional<Member> findMember = memberRepository.findByEmail(email);
if(findMember.isPresent()) {
throw new BusinessException(ErrorCode.EMAIL_DUPLICATE);
}
}
}
아래는 단위 테스트 코드입니다.
@ExtendWith(MockitoExtension.class)
class MemberServiceImplTest {
@Mock
private MemberRepository memberRepository;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private RedisService redisService;
@InjectMocks
private MemberServiceImpl memberService;
@BeforeEach
void setUp() {
reset(memberRepository, passwordEncoder, redisService);
}
@Test
@DisplayName("회원 가입 성공")
void signUp_Success() {
// given
MemberRequest memberRequest = createMemberRequest();
String encodedPassword = "encodedPassword";
given(memberRepository.findByLoginId(memberRequest.getLoginId())).willReturn(Optional.empty());
given(memberRepository.findByEmail(memberRequest.getEmail())).willReturn(Optional.empty());
given(passwordEncoder.encode(memberRequest.getPassword())).willReturn(encodedPassword);
willDoNothing().given(redisService).verifyAuthNum(memberRequest.getEmail(), memberRequest.getAuthNum());
willDoNothing().given(redisService).deleteKey(memberRequest.getEmail());
// when
Member member = memberService.signUp(memberRequest);
// then
assertNotNull(member);
assertEquals(member.getLoginId(), memberRequest.getLoginId());
assertEquals(member.getEmail(), memberRequest.getEmail());
assertEquals(member.getNickname(), memberRequest.getNickname());
assertEquals(member.getPassword(), encodedPassword);
assertEquals(member.getRole(), Role.MEMBER);
assertEquals(member.getSns(), Sns.NONE);
verify(memberRepository, times(1)).save(any(Member.class));
verify(memberRepository, times(1)).findByLoginId(any());
verify(memberRepository, times(1)).findByEmail(any());
verify(passwordEncoder, times(1)).encode(any());
verify(redisService, times(1)).verifyAuthNum(any(), any());
verify(redisService, times(1)).deleteKey(any());
}
}
답변을 작성해보세요.
0
인프런 AI 인턴
2024.05.08
안녕하세요, 인프런 AI 인턴입니다.
상언님, 단위 테스트 작성에 대해 질문 주셨군요. 제공해주신 코드를 보면, 단위 테스트의 기본 구조를 이해하고 잘 작성하셨습니다. Mockito를 사용하여 의존성을 가진 컴포넌트를 목 객체로 만들어 실제 환경과 분리된 상태에서 테스트를 진행한 점이 특히 좋습니다. 몇 가지 추가적인 제안을 드리자면:
가독성 향상:
@DisplayName
을 사용하여 각 테스트 케이스의 목적을 더 명확하게 기술하신 점이 좋습니다. 계속해서 모든 테스트 케이스에 대해 명확한 설명을 작성해 주세요. 이렇게 되면 테스트 코드를 읽는 다른 개발자들이 더 쉽게 이해할 수 있습니다.예외 상황 테스트: 현재 성공 케이스에 대한 테스트가 잘 작성되어 있습니다. 추가적으로 회원가입 과정에서 발생할 수 있는 예외 상황들도 테스트해보는 것이 좋습니다. 예를 들어, 중복된 로그인 ID나 이메일로 회원가입을 시도했을 때, 적절한 예외가 발생하는지 검증하는 테스트를 추가해보세요.
Edge Case 검증: 회원가입 데이터(validation) 검증 과정에서 잘못된 입력값이 들어왔을 때의 상황도 테스트해보는 것이 좋습니다. 예를 들어, 비밀번호나 이메일 형식이 잘못된 경우의 처리를 확인할 수 있습니다.
성능 및 리소스 검증: 테스트에서는 단순히 기능적인 측면 뿐만 아니라 리소스 사용, 성능 등도 간단하게나마 검토할 필요가 있습니다. 예를 들어,
@MockBean
을 이용한 서비스나 리포지토리가 너무 많은 작업을 하지 않는지, 비효율적으로 리소스를 사용하지 않는지 확인해볼 수 있습니다.통합 테스트 고려: 단위 테스트 외에도, Spring Boot의
@WebMvcTest
나@SpringBootTest
등을 활용한 통합 테스트를 작성하는 것도 고려해보세요. 이를 통해 실제 애플리케이션 컨텍스트에서의 상호작용도 검증할 수 있습니다.
제공해주신 정보에서는 @WebMvcTest
등의 사용 예를 확인할 수 있는데, 이는 컨트롤러 레이어의 테스트에 매우 유용합니다. 회원가입 기능이 웹 어플리케이션의 일부라면, 해당 애노테이션을 사용한 컨트롤러 테스트도 고려해볼 만합니다.
단위 테스트는 애플리케이션의 견고성을 높이고, 리팩토링이나 기능 추가 시 안정성을 보장하는 데 중요한 역할을 합니다. 처음이라 어려움을 느낄 수 있지만, 지속적으로 다양한 케이스에 대해 테스트 코드를 작성해보면 능숙해질 것입니다.
도움이 될 만한 자료를 공유해드립니다.
Spring Boot 참조 문서 - 스프링 부트 애플리케이션 테스트
Spring Boot 참조 문서 - 스프링 시큐리티와 함께 테스트
화이팅입니다!
답변 1