Hi Romain
> From: Romain Manni-Bucau <[email protected]>
>
> Hi Xavier,
>
> 2017-04-05 12:22 GMT+02:00 Xavier Dury <[email protected]>:
>
>> 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();
}
}