이 글은 이동욱 님의 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 책을 읽으며 정리한 글입니다.
JPA 구성과 스프링 시큐리티를 적용한 후 이전에 작성했던 테스트들을 돌려 보면 아래와 같이 통과되지 않는다. @WebMvcTest의 특성을 정리하고 인증된 사용자를 추가하는 방법을 알아보자!
🎆 @EnableJpaAuditing은 엔티티를 필요로 한다
- Error creating bean with name 'jpaAuditingHandler'
- JPA metamodel must not be empty!
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: 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
는 엔티티의 이벤트를 추적한다. 엔티티 데이터의 생성 일자와 수정 일자를 기록하기 위해 사용했다. 이 어노테이션은 최소 하나의 엔티티를 필요로 하는데, @WebMvcTest
는 WebSecurityConfigurerAdapter
, WebMvcConfigurer
를 비롯한 @ControllerAdvice
, @Controller
를 읽을 뿐, @Repository
와 @Service
, @Component
는 스캔하지 않으므로 엔티티가 존재하지 않는 상태가 된다.
@EnableJpaAuditing
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
현재 위의 코드와 같이 @EnableJpaAuditing
가 @SpringBootApplication
과 함께 있는 상태라 1@WebMvcTest
에서도 스캔하게 된 것이다. 따라서 두 어노테이션을 아래와 같이 분리해서 스캔하지 않도록 한다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args); // WAS 실행
}
}
@Configuration
@EnableJpaAuditing
public class JpaConfig {
}
🎆 테스트에 임의로 인증된 사용자 추가하기
testImplementation("org.springframework.security:spring-security-test")
@Autowired
private WebApplicationContext context;
private MockMvc mvc;
@BeforeEach
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)
.content(new ObjectMapper().writeValueAsString(requestDto))) // 본문 영역은 문자열로 표현
.andExpect(status().isOk());
...
}
@WithMockUser
- 인증된 모의(가짜) 사용자를 만든다.
- MockMvc에서만 작동한다.
🎆 src/main과 src/test 환경 차이
src/main과 src/test는 서로 다른 환경 구성을 가진다. test에 application.propeties가 없으면 main의 설정을 그대로 가져온다. 이때 자동으로 가져오는 범위는 application.properties까지이므로 application-oauth.properties와 같은 기타 다른 설정 파일들은 가져오지 않는다.
Failed to load ApplicationContext
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.servlet.Filter]: Factory method 'springSecurityFilterChain' threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' available
따라서 test/resources에 별도의 설정 파일인 application.properties를 만들어 줬다.
resources를 resource로 생성하지 않도록 주의하자. 초반에 잘못 표기해서 이를 설정 파일로 인식하지 못했고, main의 설정 파일에 의존하게 되어 혼란스러웠다. 😧
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL
spring.h2.console.enabled=true
spring.session.store-type=jdbc
# Test OAuth
spring.security.oauth2.client.registration.google.client-id=test # 임의의 설정
spring.security.oauth2.client.registration.google.client-secret=test
spring.security.oauth2.client.registration.google.scope=profile,email
- 스프링 부트의 자동 설정, 스프링 Bean 읽기와 생성을 모두 자동으로 설정한다. 이 어노테이션이 있는 위치(메인 클래스)부터 설정을 읽기 때문에 항상 프로젝트의 최상단에 위치해야 한다. [본문으로]
'Book > 스프링 부트와 AWS 웹 서비스' 카테고리의 다른 글
[AWS] 데이터베이스 환경 구성하기 - RDS (0) | 2023.02.24 |
---|---|
[AWS] 서버 환경 구성하기 - EC2 (0) | 2023.02.22 |
스프링 시큐리티와 OAuth 2.0으로 로그인 기능 구현하기 (feat. Google, Naver) (0) | 2023.02.17 |
머스테치(Mustache)로 화면 구성하기 (0) | 2023.02.10 |
[Spring Boot] JPA로 데이터베이스 다루기 (0) | 2023.02.09 |
댓글