-
-
Notifications
You must be signed in to change notification settings - Fork 2k
[Spring] Share application context #1848
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
a176c00
5b564d3
d77e00e
37ff9ea
35fb721
48fa98c
8b6afda
6337a7a
2b2af1c
c8e1010
88ac994
0833a49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,8 +26,6 @@ | |
import java.util.Set; | ||
|
||
import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE; | ||
import static io.cucumber.spring.FixBootstrapUtils.createBootstrapContext; | ||
import static io.cucumber.spring.FixBootstrapUtils.resolveTestContextBootstrapper; | ||
import static java.util.Arrays.asList; | ||
|
||
/** | ||
|
@@ -65,6 +63,8 @@ | |
@API(status = API.Status.STABLE) | ||
public final class SpringFactory implements ObjectFactory { | ||
|
||
private static final Object monitor = new Object(); | ||
|
||
private ConfigurableListableBeanFactory beanFactory; | ||
private CucumberTestContextManager testContextManager; | ||
|
||
|
@@ -129,21 +129,28 @@ private static boolean hasAnnotation(Annotation annotation, Collection<Class<? e | |
|
||
@Override | ||
public void start() { | ||
if (stepClassWithSpringContext != null) { | ||
testContextManager = new CucumberTestContextManager(stepClassWithSpringContext); | ||
} else { | ||
if (beanFactory == null) { | ||
beanFactory = createFallbackContext(); | ||
// registerStepClassBeanDefinition and | ||
// CucumberTestContextManager.registerGlueCodeScope manipulate the the | ||
// application context. These operations are not thread-safe. So the | ||
// SpringFactory must be started serially. | ||
synchronized (monitor) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replaced the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also explained the why of it all. |
||
if (stepClassWithSpringContext != null) { | ||
testContextManager = new CucumberTestContextManager(stepClassWithSpringContext); | ||
} else { | ||
if (beanFactory == null) { | ||
beanFactory = createFallbackContext(); | ||
} | ||
} | ||
} | ||
notifyContextManagerAboutTestClassStarted(); | ||
if (beanFactory == null || isNewContextCreated()) { | ||
beanFactory = testContextManager.getBeanFactory(); | ||
for (Class<?> stepClass : stepClasses) { | ||
registerStepClassBeanDefinition(beanFactory, stepClass); | ||
notifyContextManagerAboutTestClassStarted(); | ||
if (beanFactory == null || isNewContextCreated()) { | ||
beanFactory = testContextManager.getBeanFactory(); | ||
for (Class<?> stepClass : stepClasses) { | ||
registerStepClassBeanDefinition(beanFactory, stepClass); | ||
mpkorstanje marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
GlueCodeContext.getInstance().start(); | ||
} | ||
GlueCodeContext.getInstance().start(); | ||
|
||
} | ||
|
||
@SuppressWarnings("resource") | ||
|
@@ -183,9 +190,9 @@ private boolean isNewContextCreated() { | |
private void registerStepClassBeanDefinition(ConfigurableListableBeanFactory beanFactory, Class<?> stepClass) { | ||
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; | ||
BeanDefinition beanDefinition = BeanDefinitionBuilder | ||
.genericBeanDefinition(stepClass) | ||
.setScope(SCOPE_CUCUMBER_GLUE) | ||
.getBeanDefinition(); | ||
.genericBeanDefinition(stepClass) | ||
.setScope(SCOPE_CUCUMBER_GLUE) | ||
.getBeanDefinition(); | ||
registry.registerBeanDefinition(stepClass.getName(), beanDefinition); | ||
} | ||
|
||
|
@@ -233,9 +240,7 @@ private static boolean annotatedWithSupportedSpringRootTestAnnotations(Annotatio | |
static class CucumberTestContextManager extends TestContextManager { | ||
|
||
CucumberTestContextManager(Class<?> testClass) { | ||
// Does the same as TestContextManager(Class<?>) but creates a | ||
// DefaultCacheAwareContextLoaderDelegate that uses a thread local contextCache. | ||
super(resolveTestContextBootstrapper(createBootstrapContext(testClass))); | ||
super(testClass); | ||
registerGlueCodeScope(getContext()); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,23 @@ | ||
package io.cucumber.spring.threading; | ||
|
||
import io.cucumber.core.cli.Main; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.RepeatedTest; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Future; | ||
|
||
import static java.util.concurrent.Executors.newFixedThreadPool; | ||
import static org.hamcrest.CoreMatchers.is; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.junit.jupiter.api.Assertions.assertAll; | ||
|
||
class RunParallelCukesTest { | ||
class RunParallelCucumberTest { | ||
|
||
@Test | ||
void test() { | ||
@RepeatedTest(100) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're running 100 repetitions with 100 concurrent scenarios. Should tone this down a bit for CI but good enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤣 |
||
void test() throws ExecutionException, InterruptedException { | ||
Callable<Byte> runCucumber = () -> { | ||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | ||
String[] args = { | ||
|
@@ -27,14 +29,16 @@ void test() { | |
}; | ||
|
||
|
||
ExecutorService executorService = newFixedThreadPool(2); | ||
Future<Byte> result1 = executorService.submit(runCucumber); | ||
Future<Byte> result2 = executorService.submit(runCucumber); | ||
ExecutorService executorService = newFixedThreadPool(ThreadingStepDefs.concurrency); | ||
List<Future<Byte>> results = new ArrayList<>(); | ||
for (int i = 0; i < ThreadingStepDefs.concurrency; i++) { | ||
results.add(executorService.submit(runCucumber)); | ||
} | ||
|
||
assertAll("jobs completed successfully", | ||
() -> assertThat(result1.get(), is((byte) 0x0)), | ||
() -> assertThat(result2.get(), is((byte) 0x0)) | ||
); | ||
for (Future<Byte> result : results) { | ||
assertThat(result.get(), is((byte) 0x0)); | ||
} | ||
ThreadingStepDefs.map.clear(); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the
FixBootstrapUtils
. Wasn't needed any more.