728x90
반응형
테스트 코드를 작성하고 테스트하는 중, 갑자기 JPA관련 오류가 나왔다. 처음 보는 부분이고 테스트 코드에 능숙하지 않아서 당황...
에러 로그
java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration@33bdd01 testClass = dev.backend.wakuwaku.domain.oauth.controller.OauthControllerTest, locations = [], classes = [dev.backend.wakuwaku.WakuWakuApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@4d1c005e, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@3ba1fec0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@3b4b2266, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@5db6b9cd, [ImportsContextCustomizer@3ace6346 key = [org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration, org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration, org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration, org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration, org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration, org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration, org.springframework.boot.test.autoconfigure.web.reactive.WebTestClientAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration, org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcSecurityConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebClientAutoConfiguration, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcWebDriverAutoConfiguration, org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration, org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration, org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration, org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration, org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration, org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration, org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration, org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration, org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@7098b907, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@2235eaab, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@7887506c, org.springframework.boot.test.context.SpringBootTestAnnotation@85b89e3e], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
테스트 코드
@ExtendWith(RestDocumentationExtension.class)
@WebMvcTest(controllers = OauthController.class)
class OauthControllerTest {
@MockBean
private OauthService oauthService;
@MockBean
private EntityManager entityManager;
@Autowired
private MockMvc mockMvc;
@BeforeEach
void setUp(final WebApplicationContext context, final RestDocumentationContextProvider restDocumentation) {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.apply(documentationConfiguration(restDocumentation))
.alwaysDo(MockMvcResultHandlers.print())
.addFilters(new CharacterEncodingFilter("UTF-8", true))
.build();
}
@Test
@DisplayName("OAuth 로그인 테스트")
void login() throws Exception {
// given
Long memberId = 1L;
String code = "authorization_code";
Map<String, Long> responseMap = new HashMap<>();
responseMap.put("id", memberId);
given(oauthService.login(OauthServerType.GOOGLE, code)).willReturn(responseMap);
// when & then
mockMvc.perform(RestDocumentationRequestBuilders.get("/oauth/login/{oauthServerType}", OauthServerType.GOOGLE)
.queryParam("code", code))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(memberId))
.andDo(MockMvcRestDocumentationWrapper.document("oauth-login",
resource(ResourceSnippetParameters.builder()
.tag("OAuth")
.description("OAuth 로그인.")
.pathParameters(
parameterWithName("oauthServerType").description("OAuth 서버 타입: NAVER, KAKAO, GOOGLE")
)
.queryParameters(
parameterWithName("code").description("인증 코드")
)
.responseFields(
fieldWithPath("id").type(JsonFieldType.NUMBER).description("회원 ID")
)
.build()
)
));
then(oauthService).should().login(OauthServerType.GOOGLE, code);
}
}
Oauth 소셜로그인 컨트롤러 테스트 코드이다. 사실 위 테스트 코드에서의 문제가 아니었다.
계속 테스트 코드를 수정했었는데, 이유는 메인 클래스인 Application 클래스에서 사용되는 어노테이션 문제였음.
문제의 코드
@SpringBootApplication
@EnableJpaAuditing // <- 문제의 부분
@ConfigurationPropertiesScan
public class WakuWakuApplication {
public static void main(String[] args) {
SpringApplication.run(WakuWakuApplication.class, args);
}
}
@EnableJpaAuditing은 엔티티의 생성 및 수정 시간, 생성자 및 수정자 등을 자동으로 기록하고 관리할 수 있게 해주는 어노테이션이다. 이를 통해 데이터의 생성 및 수정 시점을 쉽게 추적하고 관리할 수 있어서 자주 사용되는 어노테이션이다. 이 부분 때문에 문제가 발생된 것이다.
위 어노테이션 때문에 WebMvcTest는 JPA 설정을 포함하지 않으므로 JPA와 관련된 설정이 제대로 이루어지지 않아서 JpaMetamodelMappingContext 가 빈 상태로 남은 것이다.
수정방법
1. @EnableJpaAuditing 사용하지 않고, 생성/수정 시간 따로 관리
@SpringBootApplication
//@EnableJpaAuditing
@ConfigurationPropertiesScan
public class WakuWakuApplication {
public static void main(String[] args) {
SpringApplication.run(WakuWakuApplication.class, args);
}
}
2. @MockBean(JpaMetamodelMappingContext.class) 추가
@ExtendWith(RestDocumentationExtension.class)
@WebMvcTest(controllers = OauthController.class)
@MockBean(JpaMetamodelMappingContext.class)
class OauthControllerTest {
}
위 어노테이션을 추가하면 JpaMetamodelMappingContext를 목(Mock)으로 등록하여 JPA 관련 메타모델 문제를 피할 수 있고, 이렇게 하면 @EnableJpaAuditing이 활성화된 상태에서도 테스트를 실행할 수 있다.
728x90
반응형