@Produces leads to circular dependency
Nerdy-5 opened this issue · 2 comments
Hi folks
I am currently migrating from CDI-Unit to weld-testing 2.0.2. Everything should work pretty much the same, but I have hit a snag:
Tests that use mocks:
@EnableAutoWeld
class SomeTest {
@Inject
private ABean beanThatUsesUtil;
@Produces
@ExcludeBean
@Mock
private Util mockedUtil;
@Test
....
Result:
WELD-001443: Pseudo scoped bean has circular dependencies. Dependency path:
...
Producer Field [Util] with qualifiers [@Any @default] declared as [[UnbackedAnnotatedField] @produces @ExcludeBean @mock private SomeTest.mockedUtil]
What am I missing? What can I try? These tests where working in a weld container and the code deploys fine on JBoss. Is it worth trying to get weld-junit5 4.x working with Java11 (javax instead of jakarta) or will it just fail as well?
Thanks in advance
Hello @Nerdy-5, below are some explanations.
Let me know if it helps you.
What am I missing? What can I try? These tests where working in a weld container and the code deploys fine on JBoss.
I am pretty sure your previous setup must been slightly different to avoid cyclic dependency as your issue is not with weld-testing but with how CDI itself works (last paragraph in 2.4).
The problem here is that CDI needs to instantiate a bean and inject into all of its fields in order to be able to invoke its producers. So when you ask for Util
bean, CDI knows there is a producer inside SomeTest
. However, to instantiate SomeTest
, it needs Util
for one of its injection points - hence the cycle.
Here are some things that you can try. Mind that I don't know your whole scenario so not all might be viable:
- Turn
Util
bean into normal scoped bean (bean using a proxy).- For instance by putting
@ApplicationScope
on the producer.
- For instance by putting
- Make the producer
static
- CDI won't need to create an instance of the bean to invoke the producer.
- Move the producer method into another bean
- In this case I am not sure if we process/pick it up but I think we should so long as it's a bean you use in the test
- Avoid injecting
Util
into a field - instead use it as method parameter in whichever test method you need it.- This helps because method injection points are only satisfied upon method invocation so CDI can create the bean itself without any cyclic dependency.
Is it worth trying to get weld-junit5 4.x working with Java11 (javax instead of jakarta) or will it just fail as well?
You should use version of weld-testing that's made for given Weld version (and therefore CDI version or Jakarta EE version if you wish) you are running on.
So Weld 5 = weld-testing 4.x (this is where change to jakarta
namespace happened).
Weld 4 = weld-testing 3.x (javax
namespace).
Functionally, they should be the same except minor bug fixes.
Success!
I think the difference to CDI-Unit is, that Weld-Testing makes @singletons out of the test classes. Making the producer static was simple and effective:
@Produces
@ExcludeBean
@Mock
private static Util mockedUtil;
Thank you also for clarifying which version to use. Didn't catch that before and chose the right one by chance (2.x for weld 3.x)