Commit 0e5be0ab authored by Marten Deinum's avatar Marten Deinum Committed by Phillip Webb

Allow step action to be optional

Update `SpringApplicationRunListeners` so that the step action
is optional and does not need to call `end()`.

This commit also introduces a test for the failure case showing
that there is a missed call to end with the initial solution.

See gh-22845
parent ac357283
......@@ -103,7 +103,8 @@ class SpringApplicationRunListeners {
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction) {
doWithListeners(stepName, listenerAction, StartupStep::end);
doWithListeners(stepName, listenerAction, (step) -> {
});
}
private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction,
......@@ -111,6 +112,7 @@ class SpringApplicationRunListeners {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
stepAction.accept(step);
step.end();
}
}
......@@ -141,6 +141,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
* @author Madhura Bhave
* @author Brian Clozel
* @author Artsiom Yudovin
* @author Marten Deinum
*/
@ExtendWith(OutputCaptureExtension.class)
class SpringApplicationTests {
......@@ -1179,6 +1180,29 @@ class SpringApplicationTests {
assertThat(startCount).isEqualTo(endCount);
}
@Test
void customApplicationStartupPublishStartupStepsWithFailure() {
ApplicationStartup applicationStartup = mock(ApplicationStartup.class);
StartupStep startupStep = mock(StartupStep.class);
given(applicationStartup.start(anyString())).willReturn(startupStep);
given(startupStep.tag(anyString(), anyString())).willReturn(startupStep);
given(startupStep.tag(anyString(), ArgumentMatchers.<Supplier<String>>any())).willReturn(startupStep);
SpringApplication application = new SpringApplication(BrokenPostConstructConfig.class);
application.setWebApplicationType(WebApplicationType.NONE);
application.setApplicationStartup(applicationStartup);
assertThatExceptionOfType(BeanCreationException.class).isThrownBy(application::run);
verify(applicationStartup).start("spring.boot.application.starting");
verify(applicationStartup).start("spring.boot.application.environment-prepared");
verify(applicationStartup).start("spring.boot.application.failed");
long startCount = mockingDetails(applicationStartup).getInvocations().stream()
.filter((invocation) -> invocation.getMethod().toString().contains("start(")).count();
long endCount = mockingDetails(startupStep).getInvocations().stream()
.filter((invocation) -> invocation.getMethod().toString().contains("end(")).count();
assertThat(startCount).isEqualTo(endCount);
}
private <S extends AvailabilityState> ArgumentMatcher<ApplicationEvent> isAvailabilityChangeEventWithState(
S state) {
return (argument) -> (argument instanceof AvailabilityChangeEvent<?>)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment