micronaut-gcp icon indicating copy to clipboard operation
micronaut-gcp copied to clipboard

Tests fail for GCP Http Function - Message: Binder registry is not mutable

Open c0d3-k1ra opened this issue 4 years ago • 3 comments

I wrote a test for the example GCP http function and it failed by throwing exception:

io.micronaut.context.exceptions.BeanInstantiationException at DefaultBeanContext.java:1915 Caused by: java.lang.UnsupportedOperationException at ArgumentBinderRegistry.java:38

If I remove the @MicronautTest annotation, the test passes.

Task List

  • [x] Steps to reproduce provided
  • [x] Stacktrace (if present) provided
  • [x] Example that reproduces the problem uploaded to Github
  • [x] Full description of the issue provided (see below)

Steps to Reproduce

  1. Set up this example: https://github.com/micronaut-projects/micronaut-gcp/tree/master/examples/hello-world-cloud-function
  2. Write a micronaut test with @MicronautTest annotation.
  3. Run the test.
  4. It fails

Expected Behaviour

Test should run

Actual Behaviour

Test fails to run with an an exception

Error instantiating bean of type  [io.micronaut.http.server.netty.NettyRequestArgumentSatisfier]

Message: Binder registry is not mutable
Path Taken: new NettyHttpServer(NettyHttpServerConfiguration serverConfiguration,ApplicationContext applicationContext,Router router,[RequestArgumentSatisfier requestArgumentSatisfier],MediaTypeCodecRegistry mediaTypeCodecRegistry,NettyCustomizableResponseTypeHandlerRegistry customizableResponseTypeHandlerRegistry,StaticResourceResolver resourceResolver,Provider ioExecutor,ThreadFactory threadFactory,ExecutorSelector executorSelector,ServerSslBuilder serverSslBuilder,List outboundHandlers,EventLoopGroupFactory eventLoopGroupFactory,EventLoopGroupRegistry eventLoopGroupRegistry,HttpCompressionStrategy httpCompressionStrategy,HttpContentProcessorResolver httpContentProcessorResolver,ChannelOptionFactory channelOptionFactory) --> new NettyRequestArgumentSatisfier([RequestBinderRegistry requestBinderRegistry])
io.micronaut.context.exceptions.BeanInstantiationException: Error instantiating bean of type  [io.micronaut.http.server.netty.NettyRequestArgumentSatisfier]

Message: Binder registry is not mutable
Path Taken: new NettyHttpServer(NettyHttpServerConfiguration serverConfiguration,ApplicationContext applicationContext,Router router,[RequestArgumentSatisfier requestArgumentSatisfier],MediaTypeCodecRegistry mediaTypeCodecRegistry,NettyCustomizableResponseTypeHandlerRegistry customizableResponseTypeHandlerRegistry,StaticResourceResolver resourceResolver,Provider ioExecutor,ThreadFactory threadFactory,ExecutorSelector executorSelector,ServerSslBuilder serverSslBuilder,List outboundHandlers,EventLoopGroupFactory eventLoopGroupFactory,EventLoopGroupRegistry eventLoopGroupRegistry,HttpCompressionStrategy httpCompressionStrategy,HttpContentProcessorResolver httpContentProcessorResolver,ChannelOptionFactory channelOptionFactory) --> new NettyRequestArgumentSatisfier([RequestBinderRegistry requestBinderRegistry])
	at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1915)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2630)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2616)
	at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2299)
	at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2273)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1233)
	at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1035)
	at io.micronaut.http.server.netty.$NettyHttpServerDefinition.build(Unknown Source)
	at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1888)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2630)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2616)
	at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2299)
	at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2273)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:727)
	at io.micronaut.test.extensions.AbstractMicronautExtension.beforeClass(AbstractMicronautExtension.java:206)
	at io.micronaut.test.extensions.junit5.MicronautJunit5Extension.beforeAll(MicronautJunit5Extension.java:51)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeBeforeAllCallbacks$7(ClassBasedTestDescriptor.java:359)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$273/00000000E6A4B420.execute(Unknown Source)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.invokeBeforeAllCallbacks(ClassBasedTestDescriptor.java:359)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:189)
	at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.before(ClassBasedTestDescriptor.java:78)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:132)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$224/00000000E99CB220.execute(Unknown Source)
	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:125)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$223/00000000E99CAC20.invoke(Unknown Source)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$222/00000000E99CA620.execute(Unknown Source)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$228/00000000E67A4B30.accept(Unknown Source)
	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:139)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$224/00000000E99CB220.execute(Unknown Source)
	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:125)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$223/00000000E99CAC20.invoke(Unknown Source)
	at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$222/00000000E99CA620.execute(Unknown Source)
	at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
	at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
	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.DefaultLauncher.execute(DefaultLauncher.java:248)
	at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
	at org.junit.platform.launcher.core.DefaultLauncher$$Lambda$190/00000000E6A30A20.accept(Unknown Source)
	at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
	at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:132)
	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/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 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 com.sun.proxy.$Proxy4.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:133)
	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 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.UnsupportedOperationException: Binder registry is not mutable
	at io.micronaut.core.bind.ArgumentBinderRegistry.addRequestArgumentBinder(ArgumentBinderRegistry.java:38)
	at io.micronaut.http.server.netty.binders.NettyBinderRegistrar.onCreated(NettyBinderRegistrar.java:71)
	at io.micronaut.http.server.netty.binders.NettyBinderRegistrar.onCreated(NettyBinderRegistrar.java:40)
	at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1945)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingletonInternal(DefaultBeanContext.java:2630)
	at io.micronaut.context.DefaultBeanContext.createAndRegisterSingleton(DefaultBeanContext.java:2616)
	at io.micronaut.context.DefaultBeanContext.getBeanForDefinition(DefaultBeanContext.java:2299)
	at io.micronaut.context.DefaultBeanContext.getBeanInternal(DefaultBeanContext.java:2273)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1233)
	at io.micronaut.context.AbstractBeanDefinition.getBeanForConstructorArgument(AbstractBeanDefinition.java:1035)
	at io.micronaut.http.server.netty.$NettyRequestArgumentSatisfierDefinition.build(Unknown Source)
	at io.micronaut.context.DefaultBeanContext.doCreateBean(DefaultBeanContext.java:1888)
	... 84 more

EventProcessorControllerTest > initializationError FAILED
    io.micronaut.context.exceptions.BeanInstantiationException at DefaultBeanContext.java:1915
        Caused by: java.lang.UnsupportedOperationException at ArgumentBinderRegistry.java:38

Environment Information

  • Operating System: Mac OS Catalina 10.15.6
  • Micronaut Version: 2.0.0
  • JDK Version: 11
  • ** Gradle version:** 6.5

Example Application

  • https://github.com/micronaut-projects/micronaut-gcp/tree/master/examples/hello-world-cloud-function
  • Gradle file is exactly the same.

c0d3-k1ra avatar Jul 30 '20 18:07 c0d3-k1ra

Hey, I was able to solve this.

In build.gradle if I remove

test.classpath += configurations.developmentOnly

It works.

I did not dig in much however.

c0d3-k1ra avatar Jul 31 '20 09:07 c0d3-k1ra

Workaround only works when we are not using @Inject or any bean instantiation while writing the tests.

On Digging further, I found out that NettyBinderResgistrar's onCreated method is trying to add ArgumentBinders to the registry. However, the registry is instantiated as GoogleBinderRegistry, which does not have addRequestArgumentBinder operation implemented and hence, throws an exception.

 @Override
    public RequestBinderRegistry onCreated(BeanCreatedEvent<RequestBinderRegistry> event) {
        RequestBinderRegistry registry = event.getBean(); //It is of type GoogleBinderRegistry.class
        registry.addRequestArgumentBinder(
                new BasicAuthArgumentBinder()
        );
        ....
   }

c0d3-k1ra avatar Aug 30 '20 12:08 c0d3-k1ra

Leaving this here for posterity in case this helps someone else in the future. One way to get "Binder registry is not mutable" exception is to have a mix of runtimes in your Micronaut service. In other words if you specified as your runtime something like tomcat or undertow i.e. micronaut { runtime("undertow") but somehow you declared dependency on another service which has a runtime of 'netty'. Micronaut will try to start netty with scaffolding from Servlet engine and you will get weirdness like this. I.e. take a look at your classpath and how your microservice was built.

AnthonyISS avatar Mar 22 '23 15:03 AnthonyISS