자바 프로그래밍 4주차 학습일지

학습한 내용

스프링 부트 서비스 계층 리팩토링과 테스트 코드 작성에 대해 학습
1. 서비스 계층의 인터페이스 분리
인터페이스 정의: TestService 인터페이스를 생성하여 서비스 계층의 추상화 구현
구현체 분리: TestServiceImpl 클래스에서 실제 비즈니스 로직 구현
의존성 역전 원칙: 상위 모듈이 하위 모듈에 의존하지 않도록 인터페이스 활용
2. 서비스 메서드별 역할
getAllMembers(): 전체 회원 목록 조회
saveMember(): 회원 정보 저장 (유효성 검증 포함)
getMemberById(): ID로 특정 회원 조회
deleteMember(): ID로 회원 삭제 (두 가지 방식 구현)
3. 입력값 검증 및 예외 처리
StringUtils.hasText(): 문자열 유효성 검증 유틸리티 활용
Optional 패턴: orElse(null)을 통한 안전한 데이터 조회
존재성 확인: existsById()와 findById()를 활용한 삭제 방식
4. 스프링 부트 테스트 프레임워크
@SpringBootTest: 전체 애플리케이션 컨텍스트를 로드하는 통합 테스트
@AutoConfigureMockMvc: MockMvc 자동 구성으로 웹 계층 테스트 환경 설정
MockMvc: HTTP 요청을 시뮬레이션하여 컨트롤러 테스트 수행
5. 테스트 생명주기 관리
@BeforeEach: 각 테스트 메서드 실행 전 초기화 작업
@AfterEach: 각 테스트 메서드 실행 후 데이터베이스 초기화
@DisplayName: 테스트 메서드에 의미있는 한글 설명 추가
6. HTTP 메서드별 테스트 패턴
GET/POST/DELETE: mockMvc.perform()으로 각 HTTP 메서드 테스트
응답 검증: jsonPath()를 활용한 JSON 응답 내용 검증
Given-When-Then 패턴: 테스트 시나리오를 명확하게 구조화

실습코드

// 서비스 인터페이스 public interface TestService { List<Member> getAllMembers(); Member saveMember(Member member); Member getMemberById(Long id); boolean deleteMember(Long id); } // 서비스 구현체 @Service public class TestServiceImpl implements TestService { final MemberRepository memberRepository; @Override public Member saveMember(Member member) { String name = member.getName() == null ? "" : member.getName(); if(!StringUtils.hasText(name)){ return null; } member.setName(name); return memberRepository.save(member); } @Override public boolean deleteMember(Long id) { if (memberRepository.existsById(id)) { memberRepository.deleteById(id); return true; } else { return false; } } } // 컨트롤러 테스트 @SpringBootTest @AutoConfigureMockMvc class TestControllerTest { @Autowired protected MockMvc mockMvc; @DisplayName("전부 가지고 오는 api 테스트") @Test void getAllMembers() throws Exception { // given final String url = "/members"; Member saved = memberRepository.save(new Member(1L, "seo")); // when final ResultActions result = mockMvc.perform( get(url).accept(MediaType.APPLICATION_JSON)); // then - 검증 result.andExpected(status().isOk()) .andExpect(jsonPath("$[0].id").value(saved.getId())); } }
TypeScript
복사
1.
인터페이스 기반 서비스 설계
추상화 구현: TestService 인터페이스로 서비스 계층의 공통 메서드 정의
생성자 주입: final 키워드와 함께 생성자 주입으로 의존성 불변성 보장
2.
입력값 검증 로직
null 안전성: member.getName() == null 체크로 NullPointerException 방지
문자열 검증: StringUtils.hasText()로 빈 문자열과 공백 문자열 모두 검증
3.
삭제 메서드 구현
existsById() 방식: 존재성을 먼저 확인한 후 삭제 수행으로 효율적인 조회
boolean 반환: 삭제 성공/실패 여부를 명확하게 반환
4.
테스트 환경 및 검증
통합 테스트: @SpringBootTest로 실제 애플리케이션 컨텍스트 로드
Given-When-Then: 테스트 시나리오를 명확한 3단계로 구분
JSON 응답 검증: jsonPath()를 활용하여 응답 JSON의 특정 필드값 검증