tomee-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Xavier Dury <kal...@hotmail.com>
Subject Re: ApplicationComposer and qualified mocks
Date Wed, 05 Apr 2017 12:44:26 GMT
OK, I'll try to provide a patch when I can find some time.

> From: Romain Manni-Bucau <rmannibucau@gmail.com>
>     
> I think I get the use case. Do you want to try to patch openejb-mockito?
> 
> 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
View raw message