tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Romain Manni-Bucau <rmannibu...@gmail.com>
Subject Re: ApplicationComposer and qualified mocks
Date Wed, 05 Apr 2017 12:00:25 GMT
I think I get the use case. Do you want to try to patch openejb-mockito?


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2017-04-05 13:28 GMT+02:00 Xavier Dury <kalgon@hotmail.com>:

> Hi Romain
>
> > From: Romain Manni-Bucau <rmannibucau@gmail.com>
> >
> > Hi Xavier,
> >
> > 2017-04-05 12:22 GMT+02:00 Xavier Dury <kalgon@hotmail.com>:
> >
> >> Hi,
> >>
> >> When using ApplicationComposer, I can declare mocks in my test classes
> >> like that:
> >>
> >> @Mock
> >> MyDependency myDependency;
> >>
> >> @MockInjector
> >> public Class<?> mockInjector() { return MockitoInjector.class; }
> >>
> >> But that does not seem to work with (un@Named) qualified mocks:
> >
> > Hmm, MockitoInjector has no link with CDI, it is for EJB injections
> (which
> > are not using CDI/@Inject)
> >
> >> @Mock
> >> @MyQualifier
> >> MyDependency myDependency;
> >
> > This looks like a cdi injection but @Inject is missing
>
> No, this is no CDI injection, it is the declaration of the qualified mock
> in my test class.
> That field is set by MockitoAnnotations.initMocks() (through MockInjector).
>
> >> Of course, I can still make a producer for the qualified mock like this:
> >>
> >> @Produces
> >> @MyQualifier
> >> MyDependency myDependency() { return Mockito.mock(MyDependency.class);
> }
> >>
> >> But I wanted to know if that was the only way to do it because, now, I
> >> have to programmatically create the mock instead of declaring it with
> @Mock.
> >
> > The openejb-mockito extension only supports @Default and @Any qualifiers
> (
> > https://github.com/apache/tomee/blob/master/utils/
> openejb-mockito/src/main/java/org/apache/openejb/mockito/
> MockitoExtension.java)
> > but no real blocker to support another one. The only issue is to define
> how
> > to select an instance based on a qualifier then.
> >
> > Note: @Named is not a "real" qualifier so you actually used @Default I
> think
>
> When MockRegistry is looping on all the fields of the TestInstance to
> gather
> the mocks created by MockitoAnnotations.initMocks(), it should also keep
> all
> qualifiers declared on the field.
>
> Of course, this is not trivial with stereotypes and qualifiers added at
> runtime
> through BeforeBeanDiscover.addQualifier() (but all annotations could be
> kept and
> filtered in the MockitoExtension which has access to the BeanManager).
>
> MockitoExtension would then need to register a bean for each mock with the
> correct type AND qualifiers.
>
> Here is a full example of what I want to do:
>
> @RunWith(ApplicationComposer.class)
> @Classes(cdi = true, innerClassesAsBean = true)
> public class MyTest {
>
>     public static class MyBean {
>
>         @Inject
>         @MyQualifier
>         public MyInterface myInterface;
>
>         public void printMessage() {
>             System.out.println(myInterface.getMessage());
>         }
>     }
>
>     public interface MyInterface {
>         String getMessage();
>     }
>
>     @Retention(RetentionPolicy.RUNTIME)
>     @Qualifier
>     public @interface MyQualifier {}
>
>     @Inject
>     private MyBean myBean;
>
>     @Mock
>     @MyQualifier
>     private MyInterface myInterface;
>
>     @Test
>     public void test() {
>         Mockito.doReturn("Hello world!").when(myInterface).getMessage();
>         myBean.printMessage();
>         Mockito.verify(myInterface).getMessage();
>     }
>
>     @MockInjector
>     public Class<? extends FallbackPropertyInjector> mockInjector() {
>         return MockitoInjector.class;
>     }
> }
>
> Currently, that does not work because MyBean.myInterface won't be resolved.
>
> My current workaround is:
>
> @RunWith(ApplicationComposer.class)
> @Classes(cdi = true, innerClassesAsBean = true)
> public class MyTest {
>
>     public static class MockProducer {
>
>         @Produces
>         @MyQualifier
>         static MyInterface myInterface = Mockito.mock(MyInterface.class);
>     }
>
>     public static class MyBean {
>
>         @Inject
>         @MyQualifier
>         public MyInterface myInterface;
>
>         public void printMessage() {
>             System.out.println(myInterface.getMessage());
>         }
>     }
>
>     public interface MyInterface {
>         String getMessage();
>     }
>
>     @Retention(RetentionPolicy.RUNTIME)
>     @Qualifier
>     public @interface MyQualifier {}
>
>     @Inject
>     private MyBean myBean;
>
>     @Inject
>     @MyQualifier
>     private MyInterface myInterface;
>
>     @Test
>     public void test() {
>         Mockito.doReturn("Hello world!").when(myInterface).getMessage();
>         myBean.printMessage();
>         Mockito.verify(myInterface).getMessage();
>     }
> }

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message