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 Thu, 06 Apr 2017 07:24:40 GMT
Hi Romain,

I made a gist and wanted your opinion before I submit a PR:

https://gist.github.com/kalgon/ee1e00c0fecdd86afb01fe1a6891454a

I don't use MockRegistry or MockitoInjector anymore (everything happens in the extension)
and wanted to know if that was ok for you.

> From: Xavier Dury <kalgon@hotmail.com>
>     
> 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