AppConfig에 Thymeleaf 관련 설정을 직접 구성.ApplicationContext 로딩 중 예외 발생:java.lang.IllegalStateException: No ServletContext set
AppConfig.java@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.chilluminati.chillstock")
public class AppConfig implements WebMvcConfigurer {
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML");
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("/static/");
}
}
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
class AppConfigTest {
@Autowired
private SpringTemplateEngine templateEngine;
@Test
void thymeleafEngineIsNotNull() {
assertNotNull(templateEngine);
}
}
혹시 테스트코드에서 빈으로 등록이 안되었나 했지만 AppConfig가 @Configuration이므로 templateResolver(), templateEngine()는 테스트 환경에서도 정상적으로 등록되는것을 확인했다.
테스트 코드에 있던 @EnableWebMvc가 문제였다.
@EnableWebMvc는 WebMvcConfigurationSupport를 통해 Spring MVC 관련 설정(예: HandlerMapping, ResourceHandlerMapping 등)을 자동 등록한다.ServletContext가 필요하지만 테스트 환경에서는 기본적으로 존재하지 않았는데 이 때문에 No ServletContext set 예외가 발생했던 것이다.@WebAppConfiguration 추가@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = AppConfig.class)
@WebAppConfiguration
class AppConfigTest {
...
}
@WebAppConfiguration은 테스트 컨텍스트를 WebApplicationContext로 전환MockServletContext를 만들어 Spring에게 전달ServletContext를 공급resourceHandlerMapping 같은 MVC 구성도 정상 작동ServletContext를 생성하고 Spring에 전달한다.MockServletContext가 필요했던 것이다.templateEngine만 테스트하고 싶을 때Thymeleaf 관련 빈만 테스트하려면 AppConfig에서 @EnableWebMvc를 제거한 별도 설정 클래스를 만들어 테스트에 주입할 수도 있다.@Configuration
public class ThymeleafOnlyConfig {
@Bean
public SpringResourceTemplateResolver templateResolver() { ... }
@Bean
public SpringTemplateEngine templateEngine() { ... }
}
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ThymeleafOnlyConfig.class)
class TemplateEngineTest {
@Autowired
SpringTemplateEngine engine;
@Test
void engineNotNull() {
assertNotNull(engine);
}
}
| 구분 | 설명 |
|---|---|
| 실제 서버 실행 시 | 서블릿 컨텍스트 자동 제공 → MVC 구성 정상 |
| 테스트 실행 시 | ServletContext 없음 → @WebAppConfiguration 필수 |
| 테스트 실패 원인 | @EnableWebMvc로 생성되는 MVC 구성 요소가 서블릿 컨텍스트 필요 |
| 해결 | 테스트 클래스에 @WebAppConfiguration 추가 |
| 대안 | Thymeleaf만 테스트할 경우 MVC 설정 분리 가능 |
난 템플릿 엔진만 테스트 하고 싶은데 해당 설정이 webmvc에 들어가 있어서 테스트 코드가 @EnableWebMvc 에 종속되는 결과를 낳았다.
따라서 thymeleaf관련 설정 클래스를 따로 빼고 해당 클래스를
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { ThymeleafConfig.class };// DB 설정이 따로 있다면 여기에 추가 기타 컨픽도 추가
}
에 추가하여 구조를 바꾸고 테스트코드도 다음과 같이 사용할 수 있었다.
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ThymeleafConfig.class)
class WebMvcConfigTest {
@Autowired
private SpringTemplateEngine templateEngine;
@Test
public void thymeleafEngineIsNotNull() {
assertNotNull(templateEngine);
}
}
실제로 이렇게 구조화 하는게 추가적으로 의존성이 추가될때 보기도 편하고 유지보수 하는데도 유리할 것이라고 판단하여 앞으로 mtbatis 나 히카리 등 추가할떄도 이 방법을 쓰기로 하였다.