@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
/ *
* Copyright 2012 - 2024 the original author or authors .
* Copyright 2012 - 2025 the original author or authors .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
@ -51,6 +51,7 @@ import org.springframework.boot.availability.AvailabilityChangeEvent;
@@ -51,6 +51,7 @@ import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.testsupport.system.CapturedOutput ;
import org.springframework.boot.testsupport.system.OutputCaptureExtension ;
import org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer ;
import org.springframework.boot.web.server.WebServer ;
import org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean ;
import org.springframework.boot.web.servlet.FilterRegistrationBean ;
import org.springframework.boot.web.servlet.ServletContextInitializer ;
@ -81,6 +82,7 @@ import static org.mockito.ArgumentMatchers.any;
@@ -81,6 +82,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString ;
import static org.mockito.BDDMockito.given ;
import static org.mockito.BDDMockito.then ;
import static org.mockito.BDDMockito.willThrow ;
import static org.mockito.Mockito.atMost ;
import static org.mockito.Mockito.inOrder ;
import static org.mockito.Mockito.mock ;
@ -211,6 +213,48 @@ class ServletWebServerApplicationContextTests {
@@ -211,6 +213,48 @@ class ServletWebServerApplicationContextTests {
assertThat ( listener . receivedEvents ( ) ) . isEmpty ( ) ;
}
@Test
void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyed ( ) {
addWebServerFactoryBean ( ) ;
this . context . registerBeanDefinition ( "refreshFailure" , new RootBeanDefinition ( RefreshFailure . class ) ) ;
assertThatExceptionOfType ( BeanCreationException . class ) . isThrownBy ( this . context : : refresh ) ;
WebServer webServer = this . context . getWebServer ( ) ;
then ( webServer ) . should ( times ( 2 ) ) . stop ( ) ;
then ( webServer ) . should ( ) . destroy ( ) ;
}
@Test
void whenContextRefreshFailedThenWebServerStopFailedCatchStopException ( ) {
addWebServerFactoryBean ( ) ;
this . context . registerBeanDefinition ( "refreshFailure" , new RootBeanDefinition ( RefreshFailure . class , ( ) - > {
willThrow ( new RuntimeException ( "WebServer has failed to stop" ) ) . willCallRealMethod ( )
. given ( this . context . getWebServer ( ) )
. stop ( ) ;
return new RefreshFailure ( ) ;
} ) ) ;
assertThatExceptionOfType ( BeanCreationException . class ) . isThrownBy ( this . context : : refresh )
. withStackTraceContaining ( "WebServer has failed to stop" ) ;
WebServer webServer = this . context . getWebServer ( ) ;
then ( webServer ) . should ( ) . stop ( ) ;
then ( webServer ) . should ( times ( 0 ) ) . destroy ( ) ;
}
@Test
void whenContextRefreshFailedThenWebServerIsStoppedAndDestroyFailedCatchDestroyException ( ) {
addWebServerFactoryBean ( ) ;
this . context . registerBeanDefinition ( "refreshFailure" , new RootBeanDefinition ( RefreshFailure . class , ( ) - > {
willThrow ( new RuntimeException ( "WebServer has failed to destroy" ) ) . willCallRealMethod ( )
. given ( this . context . getWebServer ( ) )
. destroy ( ) ;
return new RefreshFailure ( ) ;
} ) ) ;
assertThatExceptionOfType ( BeanCreationException . class ) . isThrownBy ( this . context : : refresh )
. withStackTraceContaining ( "WebServer has failed to destroy" ) ;
WebServer webServer = this . context . getWebServer ( ) ;
then ( webServer ) . should ( ) . stop ( ) ;
then ( webServer ) . should ( ) . destroy ( ) ;
}
@Test
void cannotSecondRefresh ( ) {
addWebServerFactoryBean ( ) ;