当前位置: 首页 > 知识库问答 >
问题:

放心测试 IO 线程中的反应性夸克阻塞

邹山
2023-03-14

我有一个quarkus应用程序,我正在尝试使用Restasured进行测试,但在测试时出现了以下错误:

[org.jbo.res.rea.ser.cor.Runtime ExceptionMapper](vert. x-事件循环线程-1)IO线程上发生阻塞操作。这可能意味着您需要使用@io.smallrye.common.annotation.块来注释my.package.MyContler#更新(类my.package.My请求Dto)。或者,您可以注释类my.package.我的控制器,使类上的每个方法都阻塞,或者注释javax.ws.rs.core.应用程序类的子类,使整个应用程序阻塞

如果我运行这个应用程序并使用postman手动测试,这似乎不会发生,所以这似乎是一个测试设置的问题。

我的测试如下:

@QuarkusTest
public class MyTest {
  @Test
  @TestReactiveTransaction
  public void test_A() {
              Response response = given()
                      .when()
                      .accept(MediaTypes.JSON_TYPE)
                      .contentType(MediaTypes.JSON_TYPE)
                      .body("{myRequestJsonHere}")
                      .patch("/path/to/api")
                      .then()
                      .extract().response();
      // asserts

  }
}

控制器内部:

@Path("/path/to/api")
@ApplicationScoped
public class MyController{
  @Inject MyService service;

  @PATCH
  public Uni<MyResultType> update(@NotNull @RequestBody @Valid MyRequestDto request) {
     return service.update(request);
  }
}

我的服务:

@ApplicationScoped
public class MyService {
  @Inject MyRepository repository;

  @Transactional
  public Uni<MyResultType> update(MyRequestDto request) {
    return repository.findAll().firstResult()
       .onItem().transform(l -> mapping here))
       .flatMap(repository::persistAndFlush);
  }
}

我的存储库:

public interface MyRepository extends PanacheRepository<MyResultType> {
}

我也尝试将完整的测试内容包装在UniAsserter.execute(() -

我是否需要进行更多设置以确保正确使用线程?


共有2个答案

车思淼
2023-03-14

我相信,当您进行一次数据库访问时,您的线程应该被定义为阻塞

正如您的错误消息所说,您可以在方法或类上包含一个@Blocking注释。

Quarkus 关于阻塞线程的指南 使用 RESTEASY 反应编写 REST 服务

我猜你的班级可能是这样的:

import io.smallrye.common.annotation.Blocking;

@Path("/path/to/api")
@ApplicationScoped
public class MyController{
  @Inject MyService service;

  @Blocking
  @PATCH
  public Uni<MyResultType> update(@NotNull @RequestBody @Valid MyRequestDto request) {
     return service.update(request);
  }
}
米楚青
2023-03-14
匿名用户

< code>@Transactional不适用于Reactive Panache或Hibernate Reactive。您可以使用< code > @ react ivetransactional 或< code > panache . with transaction 。

您不应该使用< code > @ TestReactiveTransactional 进行测试。您正在模拟Rest调用,没有理由打开事务。我认为正在发生的事情是,您正在启动一个反应式事务,然后RestAssure将调用REST API并阻塞客户端,直到收到结果。我怀疑这是导致问题的原因。

您可以将测试的代码更改为:

@QuarkusTest
public class MyTest {

  @Test
  public void test_A() {
              Response response = given()
                      .when()
                      .accept(MediaTypes.JSON_TYPE)
                      .contentType(MediaTypes.JSON_TYPE)
                      .body("{myRequestJsonHere}")
                      .patch("/path/to/api")
                      .then()
                      .extract().response();
  }
}

服务变成:

@ApplicationScoped
public class MyService {
  @Inject MyRepository repository;

  @ReactiveTransactional
  public Uni<MyResultType> update(MyRequestDto request) {
    return repository
       .findAll()
       .firstResult()
       .map(l -> /* update the entity... */ );
  }
}

只有在创建新实体时才需要持久化。如果需要,可以将其添加回去。

 类似资料:
  • 在Java中,线程可以有不同的状态: 新建、可运行、阻止、等待、定时等待、终止 但是,当线程被IO阻塞时,其状态为“RUNNABLE”。我如何判断它是否被IO阻止?

  • 夸克有一件事我很难理解。我在Oracle中使用JPA。因此,我有错误IllegalStateExcema:您试图在IO线程上执行阻塞操作。这是不允许的,因为阻塞了IO线程,我在QUUKUS文档中查看了如何在没有这个困难的情况下进行JPA调用。但是所有的例子和文档都使用PostgreSQL或MariaDB与响应客户端。但是我没有找到任何用于经典JDBC客户端的客户端。 我找到了一个部分有效的解决方案

  • 我想测试一个简单的轮询示例https://smallrye.io/smallrye-mutiny/guides/polling并将服务的数据轮询到Kafka流中。 这是我要测试的一个类的简化示例: 下面是测试类: 我的实际示例的错误日志是: 我试图依靠Quarkus测试容器来提供Kafka的一个实例

  • 我正在使用Quarkus 0.24.0和以下扩展开发API:[cdi,反应式pg客户端,rest客户端,resteasy,resteasy jackson,security,vertx] 以下是我实施的路线之一: 在我开始使用Angular使用我的API之前,一切都运行顺利。在进行API调用之前,有一个OPTIONS请求,它失败了: 我试图在application.properties中添加以下内

  • 无法构建quarkus应用程序quarkus maven插件:2.10.0。最终[错误]由:java引起。io。IOException:无法为\target\quarkus app\quarkus\转换的字节码创建新文件系统。io上的jar[错误]。夸克斯。fs。util。ZipUtils。newZip(ZipUtils.java:133)[错误]位于io。夸克斯。部署。包装。步骤。JarResu

  • 问题内容: 我有一个在后台运行的线程正在以阻塞方式从输入设备读取事件,现在当我退出应用程序时,我想正确清理线程,但是我不能只运行pthread_join(),因为该线程由于IO阻塞而永远不会退出。 我如何正确解决这种情况?我应该发送一个pthread_kill(theard,SIGIORM)还是一个pthread_kill(theard,SIGALRM)来中断该块?那两个信号是否正确?还是有另一种