quarkus: @InjectMock doesn't work with @LoggerName

Describe the bug

In a @QuarkusTest annotated test I would expect to be able to use @InjectMock (or @InjectSpy) together with @LoggerName assuming there is a production class which also has a field annotated with the same @LoggerName annotation:

@QuarkusTest
public class LoggerTest {

    @InjectMock
    @LoggerName("foo")
    Logger logger;

    @Test
    void test() { ... }
}

When I try this I get an exception thrown:

org.junit.jupiter.api.extension.TestInstantiationException: Failed to create test instance

	at io.quarkus.test.junit.QuarkusTestExtension.initTestState(QuarkusTestExtension.java:848)
	at io.quarkus.test.junit.QuarkusTestExtension.interceptTestClassConstructor(QuarkusTestExtension.java:812)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.api.extension.InvocationInterceptor.interceptTestClassConstructor(InvocationInterceptor.java:72)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:77)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:342)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:289)
	at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:267)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$2(ClassBasedTestDescriptor.java:259)
	at java.base/java.util.Optional.orElseGet(Optional.java:369)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$3(ClassBasedTestDescriptor.java:258)
	at org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:101)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:100)
	at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:65)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:111)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:111)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
	at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.test.junit.QuarkusTestExtension.initTestState(QuarkusTestExtension.java:840)
	... 61 more
Caused by: java.lang.IllegalStateException: Unable to derive the logger name at io.quarkus.arc.impl.CurrentInjectionPointProvider$InjectionPointImpl@56826a75
	at io.quarkus.arc.runtime.LoggerProducer.getLoggerWithCustomName(LoggerProducer.java:39)
	at io.quarkus.arc.runtime.LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.create(LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.zig:231)
	at io.quarkus.arc.runtime.LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.get(LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.zig:261)
	at io.quarkus.arc.runtime.LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.get(LoggerProducer_ProducerMethod_getLoggerWithCustomName_66e0090f9ca11e7ac11138dde99fef2171e15248_Bean.zig:296)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:430)
	at io.quarkus.arc.impl.ArcContainerImpl.beanInstanceHandle(ArcContainerImpl.java:443)
	at io.quarkus.arc.impl.ArcContainerImpl.instanceHandle(ArcContainerImpl.java:413)
	at io.quarkus.arc.impl.ArcContainerImpl.instance(ArcContainerImpl.java:222)
	at io.quarkus.test.junit.mockito.internal.CreateMockitoMocksCallback.getBeanInstance(CreateMockitoMocksCallback.java:72)
	at io.quarkus.test.junit.mockito.internal.CreateMockitoMocksCallback.afterConstruct(CreateMockitoMocksCallback.java:28)
	... 66 more

Expected behavior

@LoggerName should work together with @InjectSpy and @InjectMock so that a Quarkus test can verify that the expected log messages are being logged.

Actual behavior

Test cannot be instantiated (see above).

To Reproduce

See description.

Environment (please complete the following information):

Quarkus version or git rev

Quarkus 2.0.0.CR3

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 23 (23 by maintainers)

Commits related to this issue

Most upvoted comments

@mkouba would the @Mock not work instead of @AlternativePriority(1)?

Yes, that should work too…

Possibly the test could mock / override the LoggerProducer?

Yes, something like this should work:

@Singleton
public class MyLoggerProducer {

    @AlternativePriority(1)
    @Dependent
    @Produces
    Logger getSimpleLogger(InjectionPoint injectionPoint) {
        // e.g. wrap the logger...
        return myLoggerInstance;
    }
 }

Is it really necessary to use the @Dependent scope for the @LoggerName qualifier?

It is necessary beacuse for other scopes the bean instance may be (and usually is) shared accross multiple injection points and each one can define a different logger name.

Just out of curiosity – that’s only because LoggerName.value is @Nonbinding, right? Would it be possible to make the attribute binding?

Care to open a PR with that check?