Controller
Service
Repository 각각에 대해서 테스트 코드를 작성하는 기회를 가졌다.
Repository 단에서의 테스트는 @DataJpaTest 어노테이션을 붙여주고 선행되는 엔터티들을 BeforeEach로 세팅해주고 테스트하는 과정이 전부였다. 테스트 시에는 롤백되기 때문에 걱정이 없었다.
Service 단의 테스트는 @ExtendWith(MockitoExtension.class) 어노테이션을 붙이며 단위 테스트에 공통적으로 사용할 확장 기능을 선언해주는 역할을 한다. 인자로 확장할 Extension을 명시하는데 보통 MockitoExtension를 쓴다.
Controller 단의 테스트가 조금 불편한데 Security Filter 때문에 조금 번거롭다.
@WebMvcTest(controllers = ItemController.class), @AutoConfigureMockMvc
@WebMvcTest 선언 시, MockMvc 객체가 주입되게 된다.
@WebMvcTest에서는 Web Layer 관련 빈들만 등록하기 때문에,
컨트롤러는 주입이 정상적으로 되지만, @Component로 등록된 리포지토리와 서비스는 주입이 되지 않는다.
따라서, @WebMvcTest에서 리포지토리와 서비스를 사용하기 위해서는
@MockBean을 사용하여 리포지토리와 서비스를 Mock 객체에 빈으로 등록해줘야 한다.
JpaMetamodelMappingContext도 주입을 해줘야 한다. Controller 클래스에 대한 테스트 코드 작성 시 @WebMvcTest 어노테이션을 사용하여 웹 레이어에 대한 단위 테스트를 한다. 웹 레이어만 테스트하므로 JPA 관련 빈을 사용할 일이 없으며, Mock 객체를 등록할 필요도 없었다. 하지만 테스트 코드를 실행하니 japMappingContext 빈을 생성하지 못했다는 런타임 예외가 발생
Spring Data JPA의 일부로서, 엔티티에 대한 매핑 정보를 제공하는 역할을 하는 하는 클래스. 즉, Spring 에서 JPA 엔티티의 메타데이터를 필요로 할때 해당 메타데이터를 제공해준다.
private UsernamePasswordAuthenticationToken auth(Long userId, UserRole userRole) {
UserDetailsImpl principal = Mockito.mock(UserDetailsImpl.class, Mockito.RETURNS_DEEP_STUBS);
given(principal.getUserId()).willReturn(userId);
given(principal.getUserRole()).willReturn(userRole);
given(principal.getUser().getUserRole()).willReturn(userRole);
String role = userRole.getRole();
if (!role.startsWith("ROLE_")) role = "ROLE_" + role;
return new UsernamePasswordAuthenticationToken(
principal, "N/A", List.of(new SimpleGrantedAuthority(role))
);
}
UsernamePasswordAuthenticationToken을 만들어 요청을 보낼 때마다 넣어서 보내야 한다.