스터디를 통해 스프링부트와 AWS로 혼자 구현하는 웹 서비스(저자 이동욱) 서적을 공부하는 중입니다.
공부/실습한 내용을 정리한 포스팅입니다.
책에 모르는 부분이 있으면 구글링하거나 챗gpt에 물어봐서 보충하였습니다.
(아직 초보라 모르는 부분이 많아 이것저것 다 적었습니다.)
참고한 사이트 출처는 포스팅 맨 하단에 적었습니다.
기존의 테스트에서는 바로 API 호출이 가능했지만, Spring Security 적용 후엔 인증된 사용자만이 API 호출할 수 있음.
테스트 코드마다 인증한 사용자가 호출한 것처럼 작동하도록 수정.
gradle > Tasks > verification > test 더블 클릭
CustomOAuth2UserSerivce
찾을 수 없음 문제 해결hello가_리턴된다
예외 메세지
No qualifying bean of type 'com.webservice.springboot.springboot_board.config.auth.CustomOAuth2UserService'
CustomOAuth2UserService
생성 시 필요한 소셜 로그인 관련 설정값들이 없기 때문에 발생.application-oauth.properties
에 설정값 추가했는데도 왜 설정이 없다고 할까?→ 테스트 환경을 위한 application.properties 생성. 실제로 구글 연동까지 진행은 안하므로 가짜 설정값 등록.
expected:<[200 OK]> but was:<[302 FOUND]>
Expected :200 OK
Actual :302 FOUND
spring-security-test
build.gradle 의존성에 추가. testImplementation('org.springframework.security:spring-security-test')
Posts_등록된다()
,Posts_수정된다()
에 @WithMockUser(roles="USER")
추가@WithMockUser
가 MockMvc에서만 작동하기 때문에, @SprinBootTest
에서 MockMvc 사용하도록 PostsApiControllerTest
수정. @Autowired
private WebApplicationContext context;
private MockMvc mvc;
@Before
public void setup(){
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
@Test
@WithMockUser(roles = "USER")
public void Posts_등록된다() throws Exception{
.
.
.
//when
mvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(new ObjectMapper().writeValueAsString(requestDto)))
.andExpect(status().isOk());
//then
List<Posts> all = postsRepository.findAll();
assertThat(all.get(0).getTitle()).isEqualTo(title);
assertThat(all.get(0).getContent()).isEqualTo(content);
}
@Test
@WithMockUser(roles = "USER")
public void Posts_수정된다() throws Exception {
.
.
.
//when
mvc.perform(put(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(new ObjectMapper().writeValueAsString(requestDto)))
.andExpect(status().isOk());
//then
List<Posts> all = postsRepository.findAll();
assertThat(all.get(0).getTitle()).isEqualTo(expectedTitle);
assertThat(all.get(0).getContent()).isEqualTo(expectedContent);
}
@Before
: 매번 테스트 시작 전에 MockMvc 인스턴스 생성ObjectMapper
: 본문(Body) 영역을 문자열로 표현하기 위해 ObjectMapper를 통해 문자열 JSON으로 변환.ObjectMapper
WebApplicationContext
: Spring 웹 애플리케이션에서 사용되는 ApplicationContext의 하위 인터페이스. 웹 환경에서 사용되는 Bean들을 관리하고, 웹 애플리케이션에서 필요한 서비스와 기능을 제공.(웹 환경 지원, DispatcherServlet 연동, 서블릿 환경 지원 등) 웹 애플리케이션 설정을 관리하고 웹 요청을 처리하는 데 필요한 빈들을 제공하는 중요한 Container.@WebMvcTest
에서 CustomOAuth2UserService
를 찾을 수 없음 문제 해결1에서 봤던 hello가_리턴된다
예외 메세지가 또 나옴.
No qualifying bean of type 'com.webservice.springboot.springboot_board.config.auth.CustomOAuth2UserService'
→ HelloControllerTest
과 다르게 @WebMvcTest
사용. @WebMvcTest
는 CustomOAuth2UserService
스캔을 하지 않음.
(@WebMvcTest
는 WebSecurityConfigurerAdapter, WebMvcConfigurer를 비롯한 @Controller,@ControllerAdvice를 읽음. 즉, @Repository, @Service, @Component는 스캔 대상이 아님. 웹 계층을 테스트하기 때문에, 웹 관련 빈들만 로드.)
SecurityConfig
는 읽었지만, SecurityConfig
를 생성하기 위해 필요한 CustomOAuth2UserService
는 읽을 수가 X 그래서 error 발생.
⇒ 스캔 대상에서SecurityConfig
제외
HelloControllerTest
에서 아래와 같이 추가
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = HelloController.class,
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = SecurityConfig.class)
})
public class HelloControllerTest {
hello가_리턴된다()
, helloDto가_리턴된다()
메서드에 아래와 같이 추가 @Test
@WithMockUser(roles = "USER")
public void hello가_리턴된다() throws Exception{
.
.
.
}
@Test
@WithMockUser(roles = "USER")
public void helloDto가_리턴된다() throws Exception{
.
.
.
Error creating bean with name 'jpaAuditingHandler': Cannot resolve reference to bean 'jpaMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jpaMappingContext': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: JPA metamodel must not be empty!
→ @EnableJpaAuditing
인하여 발생. @EnableJpaAuditing
사용하기 위해선 최소 하나의 @Entity
클래스가 필요한데, @WebMvcTest
라 없음. @EnableJpaAuditing
이 @SpringBootApplication
이랑 같이 있어 @WebMvcTest
에서도 스캔.
⇒ @EnableJpaAuditing
랑 @SpringBootApplication
분리.
(1) Application
클래스에서 @EnableJpaAuditing
제거
(2) config
패키지에 JpaConfig
생성 후 @Configuration
,@EnableJpaAuditing
붙이기.
package com.webservice.springboot.springboot_board.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}
※ @WebMvcTest
는 일반적인 Configuration 스캔X
※ Spring Boot에서는 @SpringBootApplication
을 사용하면 자동으로 @Configuration 어노테이션이 포함된 클래스를 스캔하여 Bean으로 등록.
※ @SpringBootApplication
는 @Configuration
, @EnableAutoConfiguration
, 그리고 @ComponentScan
어노테이션을 합친 것과 동일한 역할을 수행.
※ @WebMvcTest
은 웹과 관련된 빈들을 테스트하기 위해 @SpringBootApplication이 지정된 메인 애플리케이션 클래스를 읽어들임.