Closed shishovsa closed 10 months ago
Hello @shishovsa,
I took some time debugging this and below are my findings.
In your scenario you are using Weld-junit in a TestInstance.Lifecycle#PER_METHOD
mode (which is junit's default) meaning that Weld will attempt to start/shutdown container for each test method.
static final Weld weld = WeldInitiator.createWeld();
static {
weld.addBeanClass(ServiceFoo.class);
}
The above lines result in a configured Weld
builder stored statically. That means you are now carrying a configured builder instance between those test methods.
But you are also using a non-static setup to further configure Weld
instance:
WeldInitiator.from(weld)
.activate(RequestScoped.class)
.build();
Now, this code applies further configuration to Weld
object and is invoked repeatedly for each test method again - reapplying whatever configuration you are adding. This causes issues because there's an underlying CDI extension responsible for context activations that ends up being registered with the same static Weld
object repeatedly.
Maybe I am missing something but the setup you have seems rather weird - I recommend that you change it. You could do one of the following:
WeldInitiator
a static field which will result in a single configuration that's then reused for every test method
PER_CLASS
so that you only start CDI container once
static Weld
field and instead do the full configuration in the public @WeldSetup
fieldI understand the underlying issue here is hard to spot for users so I've sent a PR that adds some documentation - https://github.com/weld/weld-testing/pull/168
Thank you @manovotn !
Maybe I am missing something but the setup you have seems rather weird...
Basically idea was to create abstract test class with all setup: weld, mocks, dockers. Then extend simple test classes with only test logic (integration tests).
To prevent unwanted long-run initialization all services was possibly static
and PER_CLASS
.
In @AfterEach
-method system was clearing.
My trouble is that WeldInitiator
was not static field.
Alternatively case with full configuration in the @WeldSetup
also works fine.
And maybe it is better to do Weld
not static and use PER_METHOD
to reinitialize request scoped beans from test to test...
Thank you again!
```java public class SettingsManager { public String getConnectionString(){ return ""; } } @RequestScoped class ServiceFoo { @Inject private SettingsManager settingsManager; void run() { System.out.println(settingsManager.getConnectionString()); } } @ExtendWith(WeldJunit5Extension.class) abstract class AbstractWeld { private static final SettingsManager settingsManager = Mockito.mock(SettingsManager.class); @Inject protected ServiceFoo serviceFoo; static { // docker start String dockerConnectionString = "str"; // create some mocks Mockito.when(settingsManager.getConnectionString()).thenReturn(dockerConnectionString); } @WeldSetup public WeldInitiator weldInitiator = WeldInitiator.from(ServiceFoo.class) .activate(RequestScoped.class) .addBeans(MockBean.builder() .types(SettingsManager.class) .creating(settingsManager) .build()) .build(); @AfterEach void afterEach() { System.out.println("truncate docker database"); } } class ITTestCase1 extends AbstractWeld { @Test void doTest1() { serviceFoo.run(); } @Test void doTest2() { serviceFoo.run(); } } class ITTestCase2 extends AbstractWeld { @Test void doTest1() { serviceFoo.run(); } @Test void doTest2() { serviceFoo.run(); } } ```
Basically idea was to create abstract test class with all setup: weld, mocks, dockers. Then extend simple test classes with only test logic (integration tests).
That should work fine, Weld-junit will look for a singular @WeldSetup
configuration in the class hierarchy and use that.
https://github.com/weld/weld-testing/tree/master/junit5#inheritance-of-test-classes
My trouble is that
WeldInitiator
was not static field.
It's perfectly fine to have WeldInitiator
in a static field.
And maybe it is better to do Weld not static and use PER_METHOD to reinitialize request scoped beans from test to test...
That really depends on the contents of your test and the complexity to start them. Weld-junit is designed to start a minimal container so on its own it's taking very little time to boot and shouldn't cause you trouble.
When I using
static
weld object for creatingWeldInitiator
, active contexts was lost after two tests.But when I using
WeldInitiator.from(<classes>)
all tests works fine.The version of weld-junit is 2.0.2.Final, weld is 3.1.9 (Final), junit is 5.4.2.