-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mocked bean created via method is not injected in another bean #26733
Comments
/cc @geoand |
The default CDI bean scope is |
Didn't get the point, default is |
I miss read your comment, I though it was working when annotating with both |
It seems like your reproducer mixes Quarkus and Mockito annotations and also uses Kotlin to it's very hard to understand what is going on. I tried something with a sample Java project and it worked just fine. |
I removed 1 Mockito annotation, no changes.
There are two beans: A and B, B is injected in A, B is created via @Produses , A class itself annotated by @ApplicationScoped, B instance can't be mocked in tests (if I create bean B in the same way as A created it works). I did everything in the same way as it described there.
doesn't Quarkus support Kotlin? Didn't get the point. https://quarkus.io/guides/kotlin |
Quarkus does support Kotlin, of course. My point was that your sample was convoluted so it's hard to pinpoint what the problem is and as I said, a sample Java application I tried with a mock for a bean created via a |
I see. I have updated example (add java sample, unified java and kotlin codebase). Yes, java example works fine, looks like something wrong with proxy creation in kotlin example. Will try to solve on my own but it would be perfect you someone also could take a look. Thanks. |
Does a simple Kotlin project with a single |
Yes, if bean is not used anywhere else - it works. Example: But as it's shown in the test class, when this bean is used in another bean, mock is not injected there (it's relevant only for Kotlin; there is a corrupted version of the bean, even not nullable fields are null, this partially fixes it, instead of corrupted bean there is a normal instance (not a mock)). |
Something is wrong with your code and it's not Quarkus. Even doing this: open class Engine {
fun launch(retryTimes: Int): String {
println("going to retry ${retryTimes + 2} times")
return "ready"
}
} internal class MockingTest {
@Test
fun `two beans, one is created via producer, second one annotated -- it should work`() {
var engine = mock<Engine>()
whenever(engine.launch(any())).thenReturn("not ready")
}
} fails. So I am going to close this. |
My point is that the super simple Kotlin example I added above fails without running a Quarkus test, just a plain junit test |
It doesn't fail, I send a screenshoot. Also I've pushed example without using Quarkus CDI in the same file, it works. |
But making all classes as open resolves this issue, sorry, you are right. |
Could you help with one more question? It still looks like there is an issue with Quarkus. The problem with example above is final kotlin classes, as I said if I mark classes/method with I going to mock as open everything work, but in some cases I can't do it - e.g. when I want to use in CDI third-party class which is final and create it via Mockito suggest using this option. When I add it example without Quarkus CDI works correctly, but with Quarkus CDI it doesn't (looks like there are two different instances (injected and test and injected in beans). Are there other ways to deal with the case which I mentioned? When I want to mock final class and I can't mark it as open directly or via all-open plugin (third party api). Thank you. p.s. This mockito option changes behaviour, without it quarkus can't mock final class and fails: Cannot mock/spy class test.quarkus.mocking.Engine With enabled option bean is mocked, but as it shown there mockito API doesn't, work (if I mark mocked method as open it works with quarkus too). |
In order to be convinced that there is a Quarkus issue I'll need to see a very similar test that works as plain JUnit test and does not work when using At this point with all the things you mention I don't know what you expect me to test. So for me to look at this any more, I'll need to see (in your project) what I mentioned above. |
So, This class has both cases:
I also created branch with Spring DI, it works with the same setup (kotlin + final class + enabled mockito feature to work with final classes). Just to summarise:
p.s. if try to mock not final class it works fine. |
Okay, I'll have a look next week. |
It seems to me we are going in circles as I am getting the same exact errors I mentioned earlier with the latest version of your code. Even if I reduce things even further and have a simple test class like: internal class MockingTest {
private val engineManuallyCreated: Engine = mock()
@Test
fun `no Quarkus CDI -- OK`() {
whenever(engineManuallyCreated.launch(any())).thenReturn("not ready")
}
} then when I run the test I get: org.mockito.exceptions.base.MockitoException:
Cannot mock/spy class test.quarkus.mocking.Engine
Mockito cannot mock/spy because :
- final class
at app//test.quarkus.mocking.MockingTest.<init>(MockingTest.kt:62)
at java.base@17.0.2/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base@17.0.2/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base@17.0.2/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base@17.0.2/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base@17.0.2/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at app//org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:550)
at app//org.junit.jupiter.engine.execution.ConstructorInvocation.proceed(ConstructorInvocation.java:56)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at app//io.quarkus.test.junit.QuarkusTestExtension.interceptTestClassConstructor(QuarkusTestExtension.java:734)
at app//org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at app//org.junit.jupiter.api.extension.InvocationInterceptor.interceptTestClassConstructor(InvocationInterceptor.java:73)
at app//org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at app//org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at app//org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at app//org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:77)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeTestClassConstructor(ClassBasedTestDescriptor.java:355)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateTestClass(ClassBasedTestDescriptor.java:302)
at app//org.junit.jupiter.engine.descriptor.ClassTestDescriptor.instantiateTestClass(ClassTestDescriptor.java:79)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.instantiateAndPostProcessTestInstance(ClassBasedTestDescriptor.java:280)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$4(ClassBasedTestDescriptor.java:272)
at java.base@17.0.2/java.util.Optional.orElseGet(Optional.java:364)
at app//org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$testInstancesProvider$5(ClassBasedTestDescriptor.java:271)
at app//org.junit.jupiter.engine.execution.TestInstancesProvider.getTestInstances(TestInstancesProvider.java:31)
at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$prepare$0(TestMethodTestDescriptor.java:102)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:101)
at app//org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.prepare(TestMethodTestDescriptor.java:66)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$2(NodeTestTask.java:123)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:123)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:90)
at java.base@17.0.2/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base@17.0.2/java.util.ArrayList.forEach(ArrayList.java:1511)
at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at app//org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at app//org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at app//org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at app//org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at app//org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at app//org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at app//org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at app//org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at app//org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base@17.0.2/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.2/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base@17.0.2/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base@17.0.2/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74) So I really don't see the inline mocket coming into play |
I just figured out why we are seeing different results. This file has the wrong casing, which a Mac doesn't matter, but in Linux does... |
Oh, fixed the extension, thank you for this! https://github.com/vadim-hleif/test-quarkus-mocking/runs/7722415736?check_suite_focus=true |
I reopened the issue since this an actual problem, but so far I haven't been able to pinpoint the root cause. |
#27179 should take care of the problem |
Ensure that Quarkus can mock final methods of beans created by producers
…ucers Fixes: quarkusio#26733 (cherry picked from commit 3390d03)
Describe the bug
Beans which are created via
@Produces
api are not injected in others beans fields. It works fine if I annotate bean with@ApplicationScope
instead of using@Produces
.Expected behavior
Mocked bean in passed to other beans.
Actual behavior
Real bean in passed to other beans.
How to Reproduce?
example repo: https://github.com/vadim-hleif/test-quarkus-mocking
Output of
uname -a
orver
Darwin Vadims-MacBook-Pro.local 20.6.0 Darwin Kernel Version 20.6.0: Tue Oct 12 18:33:42 PDT 2021; root:xnu-7195.141.8~1/RELEASE_X86_64 x86_64
Output of
java -version
openjdk 17.0.3 2022-04-19 LTS OpenJDK Runtime Environment Zulu17.34+19-CA (build 17.0.3+7-LTS) OpenJDK 64-Bit Server VM Zulu17.34+19-CA (build 17.0.3+7-LTS, mixed mode, sharing)
GraalVM version (if different from Java)
No response
Quarkus version or git rev
2.10.2
Build tool (ie. output of
mvnw --version
orgradlew --version
)7.4.2
Additional information
No response
The text was updated successfully, but these errors were encountered: