앞으로 개발하면서 테스트 코드를 동시에 작성해나가는 능력이 필요할 듯하여 프로젝트가 끝난 오늘, 한번 만져보기로 했다.
가보자고~!
단위테스트는 잘게 쪼개려면 얼마든지 잘게 쪼갤 수 있다.
제약조건 검증, 단순 로직 동작 테스트...
기존 프로젝트대로라면 DB도 갔다오고, 네트워크 통신도 봐야하는 과정이 있다. 단위테스트는 통신에 필요한 외부 요소들을 Mock(모의로 만드는 객체)를 활용해 테스트를 진행하기 때문에 본 프로젝트보다 상대적으로 빠르게 실행된다.
외부 요소가 없고 각 테스트마다 독립적으로 실행되므로 다른 테스트에 영향을 주지 않는다.
테스트 결과를 정해놓고 작성되기 때문에 언제 실행해도 동일한 결과가 나오도록 해야 한다.
특정 메서드의 문제를 즉시 파악할 수 있다.
: 자동화 테스트 도구
테스트 실행 시
@Test: 테스트 코드라는 걸 나타낸다.@DisplayName: 테스트에 이름을 붙여준다.테스트 수명 주기
@BeforeEach: 각 테스트 실행 전에 호출@AfterEach: 각 테스트 실행 후에 호출@BeforeAll: 모든 테스트 시작 전 1회 호출@AfterAll: 모든 테스트 종료 후 1회 호출: 모의(Mocking) 프레임워크
주요 기능
@ExtendWith(MockitoExtension.class): Mockito 기능을 사용할 수 있게 해준다.(Mock 어노테이션 동작 활성화)@Mock: 가짜 객체 생성@Mock ProductRepository)@InjectMocks: @Mock으로 만든 객체들을 테스트 대상 클래스에 주입한다.@InjectMocks ProductService)when(...).thenReturn(...): 특정 메서드가 호출될 때 원하는 값을 반환하도록 설정verify(...): 특정 메서드가 예상대로 호출되었는지 확인ArgumentCaptor: 메서드 호출 시 전달된 인자 값을 캡처해 검증Spy: 실제 객체를 사용하되 특정 메서드만 스텁(가짜 동작 정의) 하거나 호출 검증을 하고 싶을 때 사용이전 과제였던 LunchVote에서 UserService 로직 중 사용자 등록 성공에 대한 테스트코드를 작성해봤다.
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
// 가짜 UserRepository 생성
@Mock
private UserRepository userRepository;
//가짜 passwordEncoder 생성
private PasswordEncoder passwordEncoder;
@InjectMocks
private UserService userService;
@Test
@DisplayName("사용자 등록 성공")
void createUserSuccess() { //올바른 이메일 입력 -> 사용자 등록 성공 test
//1. given
CreateUserRequest request = new CreateUserRequest("test@example.com",
"test1234",
"tester");
String encodedPassword = "encodedTest1234";
//email 형식 검증
when(userRepository.existsByEmail(request.getEmail())).thenReturn(false);
//비밀번호 암호화
when(passwordEncoder.encode(request.getPassword())).thenReturn(encodedPassword);
User user = User.builder()
.id(1L)
.email(request.getEmail())
.password(encodedPassword)
.name(request.getName())
.role(UserRoleEnum.USER)
.build();
//가짜 Repository의 save 메서드에
//any(User.class) User 클래스 타입의 객체가 변수로 들어오고
// when() 안의 내용이 실행되면 thenReturn() 안의 결과값이 나와야 한다.
when(userRepository.save(any(User.class))).thenReturn(user);
//2. when
GetUserResponse response = userService.save(request);
//3. then
//올바르게 매핑되었는지 확인
assertNotNull(response); //객체의 null 여부 확인
assertEquals(request.getEmail(), response.getEmail()); // 이메일이 일치하는지 확인
assertEquals(request.getName(), response.getName()); // 이름이 같은지 확인
assertEquals(UserRoleEnum.USER, response.getRole()); // role 같은지 확인
//동작 검증 verify
//1.given에서 적었던 동작(when.thenReturn ~ )이 제대로 수행(호출)되었는지 확인
verify(userRepository).existsByEmail(request.getEmail());
verify(passwordEncoder).encode(request.getPassword());
verify(userRepository).save(any(User.class));
}
}
테스트 결과는....

😱 실패
원인은 내일 찾아서 수정해보겠다...