다음은 Junit 테스트를 해보자.
src/test/java안에 똑같이 web패키지 만들고 그 안에 BookControllerIntegreTest,BookControllerUnitTest라는 클래스들을 만들었다.
각각 통합테스트, 단위테스트이다.
뭐가 다르냐면 단위테스트는 컨트롤러만 테스트를 한다. 그리고 통합테스트는 컨트롤러로 전체 우리가 만든 스프링을 테스트한다.
통합테스트는 모든 Bean을 똑같이 IoC에 올리고 테스트를 한다.
Controller 단위테스트는 Controller 관련 로직(필터라든지, 컨트롤어드바이스라든지)만 띄운다.
통합테스트는 모든 빈들을 올리니 좀 느리고 단위는 그거에 비해 빠르다, 하지만 단위테스트는 이거로 테스트하면 실제서버에서 돌때 완벽하게 돈다는 보장이 없다. 분리해서 테스트 했으니 다른거랑 같이 연결해서 쓰면 또 어떤 에러가 나올지 모르기 때문.
이렇게 WebMvcTest 어노를 붙이면 메모리에 필터라든지, 컨트롤어드바이스라든지가 뜬다.
만약 테스시 클래스를 내가 만든 스프링 환경으로 확장하고싶다면(현재 저 BookControllerUnitTest 클래스는 스프링 환경이랑 현재 아무 상관없는 클래스이다) @ExtendWith(SpringExtension.class)이 어노테이션을 꼭 붙여야한다. 하지만 여기선 이 WebMvcTest어노 안에 ExtendWith가 들어가 있다.
통합 테스트를 하려면@SpringBootTest라는 어노가 필요한데, 이걸 걸면 모든 애들이 메모리에 다 뜬다.
여기서 WebEnvironment.MOCK은 실제 톰캣을 올리는게 아니라 다른 톰캣으로 테스트를 함.
만약 이걸 WebEnvironment.RANDOM_POR로 걸면 실제 톰캣으로 테스트 한다는 것
이 두가지만 일단 확실하게 기억하자.
여기선 이 MOCK이 mvc를 테스트를 할 수 있다.
이렇게 MockMvc를 메모리에 띄우자. 이건 mcv.perform이라는 함수를 통해 컨트롤러의 주소로 테스트를 해볼 수 있는 라이브러리이다.
그 전에 @AutoConfigureMockMvc이 어노도 입력을 주어야 한다. 이것까지 해야 MockMvc가 메모리가 떠서 사용할 수 있게 된다.
그리고 각각의 테스트 함수가 종료될때마다 트랜잭션을 rollback해주기 위해 @Transactional 어노를 붙이자. 이거 붙이면 각각의 메소드가 종료될때마다 롤백이 된다.(독립적인 테스트가 가능해짐)
다음 Service클래스로 가서 보는데 이건 원래는 BookRepository를 의존성 주입해야한다. 그럼 예를들면 저장하기 기능을 실행하는데 그 기능은 bookRepository.save로 repository를 불러서 실행하기때문에 이건 더이상 단위 테스트라고 할 수 없다.
그래서 일단 @ExtendWith(MockitoExtension.class)이걸로 스프링 환경으로 바꿔주자.
private BookRepository bookRepository; 이걸 실제로 띄우면 결국은 데이터베이스도 같이 테스트를 하게 된다. 이거를 가짜 객체로 만들어서 할건데, 그 환경을 MockitoExtension이 지원한다.
이렇게 @Mock이라는 어노를 쓰면 스프링 IoC가 아닌 Mockito 메모리에 등록이 된다.
Mockito이 메모리 공간에 북서비스랑 북레포지토리가 뜨는거다. 그럼 여기 bookService에서 저장하기를 실행하면 bookRepository.save가 실행이 된다. 그럼 이 bookService자체는 bookRepository를 null로 들고 있다. 왜냐면 MockitoExtension는 bookRepository를 IoC로 들고 있지 않기때문이다. 그때 집어 넣는 방법이 있는데,
@InjectMocks이걸 쓰면 BookService객체가 만들어 질때 BookServiceUnitTest 파일에 @Mock로 등록된 모든 애들을 주입받는다.
그럼 이제 BookService가 Mockito메모리에 뜰때 bookRepository요 가짜 객체가 뜨게 된다.
이렇게 Service를 만들어준다.
다음으로 RepositoryUnitTest로 와서 데이터베이스 관련된거만 띄워야한다.
@DataJpaTest로 띄운다 이걸 쓰면 JPA관련된 애들만 메모리에 뜬다. 그리고 데이터베이스를 실제 DB로할지 가짜DB로할지 정하는게 있는데 @AutoConfigureTestDatabase(replace = Replace.ANY)이 어노를 쓰면 내장DB(가짜DB)로 테스트를 한다. 만약 Replace.NONE이라고 하면 실제 DB로 테스트를 한다. 통합테스트면 실제 DB로 해볼만 한데 이건 단위테스트이니 가짜 DB로 하도록 한다.
그리고 위에 하나하나 시행될때마다 롤백되도록 @Transactional을 걸어준다.
아까는 @Mock으로 이걸 메모리에 띄웠는데 여기선 @Mock이 아닌 @Autowired를 쓸 수 있는데 이유는 @DataJpaTest 이게 Repository들을 IoC에 등록을 해준다. 그렇기에 @Mock띄우면 bookRepository가 그냥 껍데기만 올라가므로 @Autowired로 주입을 받자.
이번 게시물은 여기까지
이 글은 유튜브 메타코딩 채널의 영상을 보며 공부한 내용을 기록한 게시글입니다.