所以,
我的 Quarkus 项目 (v2.2.2) 具有以下核心功能:
- 带有兵变的反应式postgresql数据库
- 用于不模拟存储库的测试的 h2 数据库
在编写测试时,我在 quarkus 启动期间遇到了一个错误(忘记了那个错误是什么),但是一些页面建议切换到命名数据源以避免这个问题。这在当时似乎奏效了,我的模拟存储库测试通过了。
快进一点,我尝试做一个使用数据库的测试。我现在收到此错误:
java.lang.NullPointerException: Cannot invoke "org.hibernate.reactive.mutiny.Mutiny$Session.createQuery(String)" because "em" is null
at io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.createBaseQuery(CommonPanacheQueryImpl.java:307)
at io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.createQuery(CommonPanacheQueryImpl.java:255)
at io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.lambda$list$6(CommonPanacheQueryImpl.java:221)
at io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:68)
at io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)
我的 application.yml (customers
作为命名数据源):
quarkus:
datasource:
customers:
db-kind: h2
jdbc: false
reactive:
url: h2:file:~/testdb
max-size: 20
我的测试:
@QuarkusTest
public class CustomerControllerTest {
private static final String BASE_URL = "/my-url";
@Test
public void testBasicCreation() {
final Response response = given()
.when()
.body("{\"a\":3}")
.post(BASE_URL)
.then()
.extract().response();
assertEquals(200, response.getStatusCode(), () -> "Got: " + response.prettyPrint());
assertEquals("", response.getBody().as(String.class));
}
}
我的控制器的第一步是使用这个存储库:
@ApplicationScoped
public class MyCustRepo implements io.quarkus.hibernate.reactive.panache.PanacheRepository<MyCust> {
}
和我的实体:
@Entity(name = "cust_entries")
@Data
@PersistenceUnit("customers")
public class MyCust {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@Column(name = "val")
Boolean val;
}
根据我发现的@persistenceUnit
实体对象应该关联适当的数据源。但是, Mutiny$Session 似乎为空。我错过了什么吗?
更新 1
在 Quarkus v 2.3.0 CR1 上
<properties>
<compiler-plugin.version>3.8.1</compiler-plugin.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
<maven.compiler.parameters>true</maven.compiler.parameters>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<org.mapstruct.version>1.5.0.Beta1</org.mapstruct.version>
<org.projectlombok.version>1.18.20</org.projectlombok.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
<quarkus.platform.version>2.3.0.CR1</quarkus.platform.version>
<surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
</properties>
完整的依赖树在这里:https ://www.codepile.net/pile/8jQeJ3j2
场景一:默认数据源(没有 PersistenceUnit 注解并且 application.yaml 没有数据源的名字)
在运行测试我得到这个错误:
java.lang.RuntimeException: java.lang.RuntimeException: Failed to start quarkus
Caused by: java.lang.RuntimeException: Failed to start quarkus
Caused by: java.lang.RuntimeException: javax.persistence.PersistenceException: Unable to build EntityManagerFactory
Caused by: javax.persistence.PersistenceException: Unable to build EntityManagerFactory
Caused by: java.lang.IllegalStateException: No pool has been defined for persistence unit default-reactive
场景 2:如果我将其设置为使用命名数据源,我会得到:
my.project.customer.conrtoller.CustomerControllerTest.testBasicCreation Time elapsed: 2.12 s <<< FAILURE!
org.opentest4j.AssertionFailedError:
Got: {
"details": "Error id 083dd288-ddff-463b-bfd1-dafdbbf13c98-1, java.lang.NullPointerException: Cannot invoke \"org.hibernate.reactive.mutiny.Mutiny$Session.createQuery(String)\" because \"em\" is null",
"stack": "java.lang.NullPointerException: Cannot invoke \"org.hibernate.reactive.mutiny.Mutiny$Session.createQuery(String)\" because \"em\" is null\r\n\tat io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.createBaseQuery(CommonPanacheQueryImpl.java:307)\r\n\tat io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.createQuery(CommonPanacheQueryImpl.java:255)\r\n\tat io.quarkus.hibernate.reactive.panache.common.runtime.CommonPanacheQueryImpl.lambda$list$6(CommonPanacheQueryImpl.java:221)\r\n\tat io.smallrye.context.impl.wrappers.SlowContextualFunction.apply(SlowContextualFunction.java:21)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.performInnerSubscription(UniOnItemTransformToUni.java:68)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni$UniOnItemTransformToUniProcessor.onItem(UniOnItemTransformToUni.java:57)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.forward(UniCreateFromKnownItem.java:38)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem$KnownItemSubscription.access$100(UniCreateFromKnownItem.java:26)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromKnownItem.subscribe(UniCreateFromKnownItem.java:23)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.converters.uni.UniToMultiPublisher$UniToMultiSubscription.request(UniToMultiPublisher.java:58)\r\n\tat io.smallrye.mutiny.operators.multi.MultiFlatMapOp$FlatMapMainSubscriber.onSubscribe(MultiFlatMapOp.java:163)\r\n\tat io.smallrye.mutiny.converters.uni.UniToMultiPublisher.subscribe(UniToMultiPublisher.java:26)\r\n\tat io.smallrye.mutiny.groups.MultiCreate$1.subscribe(MultiCreate.java:156)\r\n\tat io.smallrye.mutiny.operators.multi.MultiFlatMapOp.subscribe(MultiFlatMapOp.java:56)\r\n\tat io.smallrye.mutiny.groups.MultiSubscribe.withSubscriber(MultiSubscribe.java:69)\r\n\tat io.smallrye.mutiny.operators.multi.MultiSelectWhereOp.subscribe(MultiSelectWhereOp.java:30)\r\n\tat io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:40)\r\n\tat io.smallrye.mutiny.operators.multi.MultiFlatMapOp.subscribe(MultiFlatMapOp.java:56)\r\n\tat io.smallrye.mutiny.operators.AbstractMulti.subscribe(AbstractMulti.java:40)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromPublisher$PublisherSubscriber.forward(UniCreateFromPublisher.java:42)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromPublisher$PublisherSubscriber.access$100(UniCreateFromPublisher.java:30)\r\n\tat io.smallrye.mutiny.operators.uni.builders.UniCreateFromPublisher.subscribe(UniCreateFromPublisher.java:26)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransformToUni.subscribe(UniOnItemTransformToUni.java:25)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.operators.uni.UniOnItemTransform.subscribe(UniOnItemTransform.java:22)\r\n\tat io.smallrye.mutiny.operators.AbstractUni.subscribe(AbstractUni.java:36)\r\n\tat io.smallrye.mutiny.groups.UniSubscribe.withSubscriber(UniSubscribe.java:50)\r\n\tat io.smallrye.mutiny.groups.UniSubscribe.with(UniSubscribe.java:90)\r\n\tat org.jboss.resteasy.reactive.server.handlers.UniResponseHandler.handle(UniResponseHandler.java:17)\r\n\tat org.jboss.resteasy.reactive.server.handlers.UniResponseHandler.handle(UniResponseHandler.java:8)\r\n\tat org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:141)\r\n\tat io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:81)\r\n\tat io.vertx.core.impl.ContextImpl.execute(ContextImpl.java:260)\r\n\tat io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:22)\r\n\tat org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$1.execute(VertxResteasyReactiveRequestContext.java:69)\r\n\tat org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.resume(AbstractResteasyReactiveContext.java:82)\r\n\tat org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.resume(AbstractResteasyReactiveContext.java:50)\r\n\tat org.jboss.resteasy.reactive.server.handlers.InputHandler$InputListener.done(InputHandler.java:84)\r\n\tat org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$5.handle(VertxResteasyReactiveRequestContext.java:260)\r\n\tat org.jboss.resteasy.reactive.server.vertx.VertxResteasyReactiveRequestContext$5.handle(VertxResteasyReactiveRequestContext.java:254)\r\n\tat io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)\r\n\tat io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:63)\r\n\tat io.vertx.core.http.impl.HttpEventHandler.handleEnd(HttpEventHandler.java:76)\r\n\tat io.vertx.core.http.impl.Http1xServerRequest.onEnd(Http1xServerRequest.java:565)\r\n\tat io.vertx.core.http.impl.Http1xServerRequest.lambda$pendingQueue$1(Http1xServerRequest.java:127)\r\n\tat io.vertx.core.streams.impl.InboundBuffer.handleEvent(InboundBuffer.java:240)\r\n\tat io.vertx.core.streams.impl.InboundBuffer.write(InboundBuffer.java:130)\r\n\tat io.vertx.core.http.impl.Http1xServerRequest.handleEnd(Http1xServerRequest.java:546)\r\n\tat io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:71)\r\n\tat io.vertx.core.impl.DuplicatedContext.execute(DuplicatedContext.java:163)\r\n\tat io.vertx.core.http.impl.Http1xServerConnection.onEnd(Http1xServerConnection.java:189)\r\n\tat io.vertx.core.http.impl.Http1xServerConnection.onContent(Http1xServerConnection.java:179)\r\n\tat io.vertx.core.http.impl.Http1xServerConnection.handleOther(Http1xServerConnection.java:159)\r\n\tat io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:147)\r\n\tat io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:155)\r\n\tat io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:154)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)\r\n\tat io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:99)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)\r\n\tat io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)\r\n\tat io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)\r\n\tat io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)\r\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)\r\n\tat io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)\r\n\tat io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)\r\n\tat io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)\r\n\tat io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)\r\n\tat io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)\r\n\tat io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)\r\n\tat io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)\r\n\tat io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)\r\n\tat io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)\r\n\tat java.base/java.lang.Thread.run(Thread.java:832)"
} ==> expected: <200> but was: <500>
at my.project.customer.conrtoller.CustomerControllerTest.testBasicCreation(CustomerControllerTest.java:35)