서비스 단위 테스트를 작성하면서 알게 된 내용을 정리한 글입니다.
단위 테스트는 가능한 빨라야 한다.
테스트 실행이 너무 느리다면, 테스트 실행을 꺼리게 된다.
각 테스트는 서로 의존하면 안 된다. 다른 말로 객체의 상태, 메서드, 이전의 상태, 다른 메서드의 결과 등에 의존해서는 안 된다.
-> 하나가 실패할 때 잇달아서 실패하게 되므로 실패의 원인을 찾기가 어려워진다.
단위 테스트는 독립적으로, 어느 순서로 실행해도 항상 성공해야 한다.
예를 들어 UserService는 UserRepository에 의존한다. 만약 이전 테스트와 현재 테스트에서 동일한 Id 값인 이메일이 저장된다면 Id 중복으로 테스트가 실패하게 된다.
@Transactional를 붙이면 실행 후 DB를 롤백 하기 때문에 실패하지 않지만 실패하는 대상이 UserRepository 인지 UserService 인지 모호해진다.
단위테스트는 반복 가능해야 한다.
앞선 예시처럼 Id 중복으로 테스트가 실패하면 안 된다.
개발자가 직접 수동으로 확인할 필요 없이, Assert 문 등으로 확인할 수 있어야 한다.
단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다.
테스트를 진행할 때 해당 코드 이외의 의존하는 객체를 가짜로 만든 것을 의미한다.
목객체를 만들어주는 프레임워크
•테스트 대상을 독립적으로 테스트하기 위함
•실제 객체는 느릴 수 있다(네트워크, 데이터베이스 연결..)
•의존관계에 있는 다른 코드에서 오류가 날수 있음 .. 등등
테스트 대상은 ChatRoomService의 save메소드이고 ChatRoomService는 ChatRoomRepository에 의존한다.
여기서 테스트해야 할 부분은 ChatRoomService.save에서 ChatRoomRepository.save가 호출되는지 확인하는 것이다.
@ExtendWith(MockitoExtension.class)
public class ChatRoomServiceTest {
@InjectMocks
private ChatRoomService chatRoomService;
@Mock
private ChatRoomRepository chatRoomRepository;
@Test
void save(){
//given
ChatRoom chatRoom = ChatRoom.create("test");
//when
chatRoomService.save(chatRoom);
//then
verify(chatRoomRepository).save(any());
}
Spring-boot-starter-test에 이미 Mockito가 포함되어 있어 따로 의존성 추가해주지 않아도 된다.
JUnit4에서는 @RunWith 애노테이션을 사용한다.
@Mock이 붙어잇는 목객체를 초기화해주고 @InjectMocks이 붙어있는 객체에 자동으로 목객체를 의존 주입해 준다.
MockitoExtension을 사용하려면 아래와 같이 추가해 주어야 한다.
testImplementation 'org.mockito:mockito-junit-jupiter'
의존성 주입이 필요한 목객체를 생성한다.
목객체를 생성한다.
메서드의 호출 여부, 횟수 등을 확인한다.
@SpringBootTest대신 @InjectMocks, @Mock, @ExtendWith(MockitoExtension.class)를 사용함으로써 더욱 빠르게 테스트를 실행할 수 있다.
@SpringBootTest는 Ioc 컨테이너에 모든 빈을 등록하고 테스트를 진행하기 때문에 느릴 수밖에 없다.
Mockito 라이브러리를 사용함으로써 의존성을 제거해 독립적으로 테스트가 가능하다.
https://galid1.tistory.com/772
https://velog.io/@devsh/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-1-Spring-Boot-Repository-and-Service-Layer-Testing
https://dublin-java.tistory.com/49
https://jdm.kr/blog/222
https://mangkyu.tistory.com/145