1717
1818import java .lang .reflect .Field ;
1919import java .util .HashMap ;
20- import java .util .List ;
2120import java .util .Map ;
22- import java .util .Set ;
2321
2422import jakarta .enterprise .context .ApplicationScoped ;
2523import jakarta .enterprise .event .Observes ;
24+ import jakarta .enterprise .inject .Instance ;
2625import jakarta .enterprise .inject .literal .InjectLiteral ;
2726import jakarta .enterprise .inject .spi .AfterBeanDiscovery ;
27+ import jakarta .enterprise .inject .spi .AfterDeploymentValidation ;
2828import jakarta .enterprise .inject .spi .AnnotatedParameter ;
2929import jakarta .enterprise .inject .spi .Bean ;
3030import jakarta .enterprise .inject .spi .BeanManager ;
3131import jakarta .enterprise .inject .spi .Extension ;
3232import jakarta .enterprise .inject .spi .ProcessAnnotatedType ;
3333import jakarta .enterprise .inject .spi .WithAnnotations ;
34+ import jakarta .enterprise .inject .spi .configurator .AnnotatedConstructorConfigurator ;
35+ import jakarta .enterprise .inject .spi .configurator .AnnotatedFieldConfigurator ;
36+ import jakarta .enterprise .inject .spi .configurator .AnnotatedTypeConfigurator ;
3437import org .mockito .MockSettings ;
3538import org .mockito .Mockito ;
3639
@@ -41,52 +44,51 @@ public class MockBeansCdiExtension implements Extension {
4144
4245 private final Map <Class <?>, MockBean > mocks = new HashMap <>();
4346
44- void processMockBean (@ Observes @ WithAnnotations (MockBean .class ) ProcessAnnotatedType <?> obj ) throws Exception {
45- var configurator = obj .configureAnnotatedType ();
46- configurator .fields (). forEach ( field -> {
47+ void processMockBean (@ Observes @ WithAnnotations (MockBean .class ) ProcessAnnotatedType <?> obj ) {
48+ AnnotatedTypeConfigurator <?> configurator = obj .configureAnnotatedType ();
49+ for ( AnnotatedFieldConfigurator <?> field : configurator .fields ()) {
4750 MockBean mockBean = field .getAnnotated ().getAnnotation (MockBean .class );
4851 if (mockBean != null ) {
4952 Field f = field .getAnnotated ().getJavaMember ();
50- // Adds @Inject to be more user friendly
53+ // make @Inject optional
5154 field .add (InjectLiteral .INSTANCE );
52- Class <?> fieldType = f .getType ();
53- mocks .put (fieldType , mockBean );
55+ mocks .put (f .getType (), mockBean );
5456 }
55- });
56- configurator .constructors ().forEach (constructor -> {
57- processMockBeanParameters (constructor .getAnnotated ().getParameters ());
58- });
59- }
60-
61- private void processMockBeanParameters (List <? extends AnnotatedParameter <?>> parameters ) {
62- parameters .stream ().forEach (parameter -> {
63- MockBean mockBean = parameter .getAnnotation (MockBean .class );
64- if (mockBean != null ) {
65- Class <?> parameterType = parameter .getJavaParameter ().getType ();
66- mocks .put (parameterType , mockBean );
57+ }
58+ for (AnnotatedConstructorConfigurator <?> ctor : configurator .constructors ()) {
59+ for (AnnotatedParameter <?> parameter : ctor .getAnnotated ().getParameters ()) {
60+ MockBean mockBean = parameter .getAnnotation (MockBean .class );
61+ if (mockBean != null ) {
62+ Class <?> parameterType = parameter .getJavaParameter ().getType ();
63+ mocks .put (parameterType , mockBean );
64+ }
6765 }
68- });
66+ }
6967 }
7068
71- void registerOtherBeans (@ Observes AfterBeanDiscovery event , BeanManager beanManager ) {
72- // Register all mocks
73- mocks .entrySet ().forEach (entry -> {
74- event .addBean ()
75- .addType (entry .getKey ())
69+ void registerOtherBeans (@ Observes AfterBeanDiscovery event ) {
70+ // register mocks
71+ mocks .forEach ((key , value ) -> event .addBean ()
72+ .addTransitiveTypeClosure (key )
7673 .scope (ApplicationScoped .class )
7774 .alternative (true )
78- .createWith (inst -> {
79- Set <Bean <?>> beans = beanManager .getBeans (MockSettings .class );
80- if (!beans .isEmpty ()) {
81- Bean <?> bean = beans .iterator ().next ();
82- MockSettings mockSettings = (MockSettings ) beanManager .getReference (bean , MockSettings .class ,
83- beanManager .createCreationalContext (null ));
84- return Mockito .mock (entry .getKey (), mockSettings );
85- } else {
86- return Mockito .mock (entry .getKey (), Mockito .withSettings ().defaultAnswer (entry .getValue ().answer ()));
87- }
75+ .produceWith (i -> {
76+ Instance <MockSettings > msi = i .select (MockSettings .class );
77+ MockSettings settings = msi .isUnsatisfied ()
78+ ? Mockito .withSettings ().defaultAnswer (value .answer ())
79+ : msi .get ();
80+ return Mockito .mock (key , settings );
8881 })
89- .priority (0 );
90- });
82+ .priority (0 ));
83+ }
84+
85+ void initializeBeans (@ Observes AfterDeploymentValidation event , BeanManager manager ) {
86+ for (Class <?> key : mocks .keySet ()) {
87+ for (Bean <?> bean : manager .getBeans (key )) {
88+ // call toString() to force the beans to be initialized
89+ // noinspection ResultOfMethodCallIgnored
90+ manager .getReference (bean , key , manager .createCreationalContext (bean )).toString ();
91+ }
92+ }
9193 }
9294}
0 commit comments