Skip to content

Commit

Permalink
[Spring] Cleanly stop after failure to start application context
Browse files Browse the repository at this point in the history
Fixes: #2569
  • Loading branch information
mpkorstanje committed Jun 13, 2022
1 parent 2764068 commit 134f910
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 20 deletions.
21 changes: 11 additions & 10 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Removed

### Fixed
* [Spring] Cleanly stop after failure to start application context

## [7.3.5] (2022-05-10)

Expand Down Expand Up @@ -1793,16 +1794,16 @@ in `cucumber.api` stable from now on, with proper deprecation warnings in case s
<!-- Releases -->
[Unreleased]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.4...main
[7.3.4]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.3-RC1...v7.3.4
[7.3.3]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.2-RC1...v7.3.3
[7.3.2]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.1-RC1...v7.3.2
[7.3.1]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.0-RC1...v7.3.1
[7.3.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.3-RC1...v7.3.0
[7.2.3]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.2-RC1...v7.2.3
[7.2.2]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.1-RC1...v7.2.2
[7.2.1]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.0-RC1...v7.2.1
[7.2.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.1.0-RC1...v7.2.0
[7.1.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.0.0-RC1...v7.1.0
[7.3.4]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.3...v7.3.4
[7.3.3]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.2...v7.3.3
[7.3.2]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.1...v7.3.2
[7.3.1]: https://github.com/cucumber/cucumber-jvm/compare/v7.3.0...v7.3.1
[7.3.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.3...v7.3.0
[7.2.3]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.2...v7.2.3
[7.2.2]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.1...v7.2.2
[7.2.1]: https://github.com/cucumber/cucumber-jvm/compare/v7.2.0...v7.2.1
[7.2.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.1.0...v7.2.0
[7.1.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.0.0...v7.1.0
[7.0.0]: https://github.com/cucumber/cucumber-jvm/compare/v7.0.0-RC1...v7.0.0
[7.0.0-RC1]: https://github.com/cucumber/cucumber-jvm/compare/v6.11.0...v7.0.0-RC1
[6.11.0]: https://github.com/cucumber/cucumber-jvm/compare/v6.10.4...v6.11.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,14 @@ void registerDestructionCallback(String name, Runnable callback) {
}

void requireActiveScenario() {
if (sessionId == null) {
if (!isActive()) {
throw new IllegalStateException(
"Scenario scoped beans can only be created while Cucumber is executing a scenario");
}
}

boolean isActive() {
return sessionId != null;
}

}
21 changes: 13 additions & 8 deletions spring/src/main/java/io/cucumber/spring/TestContextAdaptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public final void start() {

private void notifyTestContextManagerAboutBeforeTestMethod() {
try {
Class<?> testClass = delegate.getTestContext().getTestClass();
Object testContextInstance = applicationContext.getBean(testClass);
Class<?> delegateTestClass = delegate.getTestContext().getTestClass();
Object delegateTestInstance = applicationContext.getBean(delegateTestClass);
Method dummyMethod = TestContextAdaptor.class.getMethod("cucumberDoesNotHaveASingleTestMethod");
delegate.beforeTestMethod(testContextInstance, dummyMethod);
delegate.beforeTestMethod(delegateTestInstance, dummyMethod);
} catch (Exception e) {
throw new CucumberBackendException(e.getMessage(), e);
}
Expand Down Expand Up @@ -101,8 +101,14 @@ private void registerStepClassBeanDefinition(BeanDefinitionRegistry registry, Cl
}

public final void stop() {
notifyTestContextManagerAboutAfterTestMethod();
CucumberTestContext.getInstance().stop();
// Don't invoke after test method when before test class was not invoked
// this is implicit in the existence of an active the test context
// session. This is not ideal, but Cucumber only supports 1 set of
// before/after semantics while JUnit and Spring have 2 sets.
if (CucumberTestContext.getInstance().isActive()) {
notifyTestContextManagerAboutAfterTestMethod();
CucumberTestContext.getInstance().stop();
}
notifyTestContextManagerAboutAfterTestClass();
}

Expand All @@ -116,10 +122,9 @@ private void notifyTestContextManagerAboutAfterTestClass() {

private void notifyTestContextManagerAboutAfterTestMethod() {
try {
Class<?> testClass = delegate.getTestContext().getTestClass();
Object testContextInstance = applicationContext.getBean(testClass);
Object delegateTestInstance = delegate.getTestContext().getTestInstance();
Method dummyMethod = TestContextAdaptor.class.getMethod("cucumberDoesNotHaveASingleTestMethod");
delegate.afterTestMethod(testContextInstance, dummyMethod, null);
delegate.afterTestMethod(delegateTestInstance, dummyMethod, null);
} catch (Exception e) {
throw new CucumberBackendException(e.getMessage(), e);
}
Expand Down
31 changes: 30 additions & 1 deletion spring/src/test/java/io/cucumber/spring/SpringFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.cucumber.core.backend.CucumberBackendException;
import io.cucumber.core.backend.ObjectFactory;
import io.cucumber.spring.SpringFactoryTest.FailedContextConfiguration.FailingListener;
import io.cucumber.spring.beans.Belly;
import io.cucumber.spring.beans.BellyBean;
import io.cucumber.spring.beans.DummyComponent;
Expand All @@ -22,6 +23,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;

import java.util.Optional;

Expand Down Expand Up @@ -341,6 +345,15 @@ void shouldBeStoppableWhenFacedWithMissingContextConfiguration() {
assertDoesNotThrow(factory::stop);
}

@Test
void shouldBeStoppableWhenFacedWithFailedApplicationContext() {
final ObjectFactory factory = new SpringFactory();
factory.addClass(FailedContextConfiguration.class);

assertThrows(RuntimeException.class, factory::start);
assertDoesNotThrow(factory::stop);
}

@CucumberContextConfiguration
@ContextConfiguration("classpath:cucumber.xml")
public static class WithSpringAnnotations {
Expand All @@ -366,7 +379,7 @@ public String getProperty() {
}

@CucumberContextConfiguration
@ContextConfiguration()
@ContextConfiguration
public static class WithEmptySpringAnnotations {

}
Expand All @@ -376,4 +389,20 @@ public static class WithoutContextConfiguration {

}

@CucumberContextConfiguration
@ContextConfiguration("classpath:cucumber.xml")
@TestExecutionListeners(FailingListener.class)
public static class FailedContextConfiguration {

public static class FailingListener implements TestExecutionListener {

@Override
public void beforeTestClass(TestContext testContext) {
throw new RuntimeException("Boom");
}

}

}

}

0 comments on commit 134f910

Please sign in to comment.