Quarkus - 测试应用程序

学习如何测试 Quarkus 应用程序。 本指南涵盖:

  • 在 JVM 模式下测试

  • 在原生(native)模式下测试

  • 将资源注入测试代码中

1. 准备

要完成本指南,您需要:

  • 15 分钟以内

  • 开发工具 IDE

  • 安装 JDK 8 或 11+,正确配置 JAVA_HOME

  • Apache Maven 3.6.2+

  • 完成 入门指南 中的 greeter 应用程序

2. 架构

在本指南中,我们将扩展 入门指南 ,创建测试部分。 将介绍注入到测试代码及如何测试原生可执行文件。

3. 完整源码

建议您按照后续说明逐步创建应用程序。 当然您也可以直接查看完成后的代码。

克隆 git 仓库: git clone https://github.com/quarkusio/quarkus-quickstarts.git , 或下载 压缩包

代码位于 getting-started-testing 目录中。

本指南假定您已经从 getting-started 目录中获得了完整的应用程序。

4. 回顾 JVM 模式下基于 HTTP 的测试

如果您是从 入门指南 示例开始的,则您应该已经完成​​了测试,包括正确的 pom.xml 设置。

pom.xml 文件中,您应该看到2个测试依赖项:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <scope>test</scope>
</dependency>

测试必需引入 quarkus-junit5 ,因为它提供了 @QuarkusTest 注解来控制测试框架。 rest-assured 并不是必需的,但它是测试 HTTP 接口的便捷方法,我们还提供了集成功能,该功能可自动设置正确的 URL ,因此无需进行配置。

因为我们使用的是 JUnit 5,所以 必须设置 Surefire Maven 插件 版本, 因为默认版本不支持 Junit 5 :

<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>${surefire-plugin.version}</version>
    <configuration>
       <systemProperties>
          <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
       </systemProperties>
    </configuration>
</plugin>

我们还设置了 java.util.logging 系统属性,以确保测试将使用正确的 logmanager 。

该项目还应该包含一个简单的测试:

package org.acme.getting.started.testing;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;

import java.util.UUID;

import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;

@QuarkusTest
public class GreetingResourceTest {

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/hello")
          .then()
             .statusCode(200)
             .body(is("hello"));
    }

    @Test
    public void testGreetingEndpoint() {
        String uuid = UUID.randomUUID().toString();
        given()
          .pathParam("name", uuid)
          .when().get("/hello/greeting/{name}")
          .then()
            .statusCode(200)
            .body(is("hello " + uuid));
    }

}

该测试使用 HTTP 直接测试我们的 REST 接口。运行测试时,将在运行测试之前启动应用程序。

4.1. 控制测试端口

尽管 Quarkus 默认会监听 8080 端口,但运行测试时默认为 8081 。 这使您可以在运行应用程序时运行测试。

更改测试端口

您可以在 application.properties 中的 quarkus.http.test-port 配置测试使用的端口:

quarkus.http.test-port=8083

Quarkus还提供了 RestAssured 集成,会在运行测试之前配置 RestAssured 使用的默认端口,因此不需要其他配置。

4.2. 注入 URI

也可以通过 @TestHTTPResource 注解直接将 URL 注入测试中,从而可以轻松使用其他客户端。

让我们写一个简单的测试,展示一下如何加载一些静态资源。 首先在中创建一个简单的 HTML 文件 src/main/resources/META-INF/resources/index.html

<html>
    <head>
        <title>Testing Guide</title>
    </head>
    <body>
        Information about testing
    </body>
</html>

我们将创建一个简单的测试,以确保此文件能正常访问:

package org.acme.getting.started.testing;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import io.quarkus.test.common.http.TestHTTPResource;
import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class StaticContentTest {

    @TestHTTPResource("index.html") (1)
    URL url;

    @Test
    public void testIndexHtml() throws Exception {
        try (InputStream in = url.openStream()) {
            String contents = readStream(in);
            Assertions.assertTrue(contents.contains("<title>Testing Guide</title>"));
        }
    }

    private static String readStream(InputStream in) throws IOException {
        byte[] data = new byte[1024];
        int r;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        while ((r = in.read(data)) > 0) {
            out.write(data, 0, r);
        }
        return new String(out.toByteArray(), StandardCharsets.UTF_8);
    }
}
1 此注解允许直接注入 Quarkus 实例的 URL ,注入的值将是 URL 的路径部分

目前通过 @TestHTTPResource 可以注入 URI, URLString 类型的网址。

5. 注入到测试中

到目前为止,我们仅介绍了通过 HTTP 接口测试应用程序的集成式测试, 但是如果我们要进行单元测试并直接测试我们的 bean,该怎么办?

Quarkus 可以通过 @Inject 注解将 CDI bean 注入到测试中 (事实上,Quarkus 中的测试是完整的 CDI bean,因此您可以使用所有 CDI 功能)。 让我们创建一个简单的测试,不使用 HTTP 直接测试接口:

package org.acme.getting.started.testing;

import javax.inject.Inject;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;

@QuarkusTest
public class GreetingServiceTest {

    @Inject (1)
    GreetingService service;

    @Test
    public void testGreetingService() {
        Assertions.assertEquals("hello Quarkus", service.greeting("Quarkus"));
    }
}
1 GreetingService bean 将被注入到测试中

6. 将拦截器应用于测试

如上所述,Quarkus 测试实际上是完整的 CDI bean, 因此您可以像平常一样应用 CDI 拦截器。 比如,如果您希望测试方法在事务的上下文中运行,则可以简单地在方法加上注解 @Transactional ,事务拦截器将对其进行处理。

除此之外,您还可以创建自己的测试原型 (stereotypes)。 例如,我们可以创建 @TransactionalQuarkusTest 如下:

@QuarkusTest
@Stereotype
@Transactional
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TransactionalQuarkusTest {
}

如果我们将此注解加在测试类上,它将像我们同时加了 @QuarkusTest 和 `@Transactional`注解一样,例如:

@TransactionalQuarkusTest
public class TestStereotypeTestCase {

    @Inject
    UserTransaction userTransaction;

    @Test
    public void testUserTransaction() throws Exception {
        Assertions.assertEquals(Status.STATUS_ACTIVE, userTransaction.getStatus());
    }

}

7. 模拟(Mock)支持

Quarkus 支持采用 CDI @Alternative 机制来模拟 (mock) 对象。 要使用此方法,只需在 src/test/java 目录下覆盖您希望模拟的 bean ,并在 mock bean 加上注解 @Alternative and @Priority(1) 。 或者,可以使用便利注解 io.quarkus.test.Mock 。 此注解声明了 @Alternative, @Priority(1)@Dependent。 例如,如果我有以下服务:

@ApplicationScoped
public class ExternalService {

    public String service() {
        return "external";
    }

}

我可以在 src/test/java 下的使用 mock 类来 mock 它:

@Mock
@ApplicationScoped (1)
public class MockExternalService extends ExternalService {

    @Override
    public String service() {
        return "mock";
    }
}
1 Overrides the @Dependent scope declared on the @Mock stereotype.

It is important that the alternative be present in the src/test/java directory rather than src/main/java, as otherwise it will take effect all the time, not just when testing.

Note that at present this approach does not work with native image testing, as this would required the test alternatives to be baked into the native image.

1 覆盖 @Mock 原型中声明的 @Dependent

重要的是,替代项应出现在 src/test/java 目录中而不是 src/main/java ,否则它将一直有效,而不仅仅是在测试时。

请注意,目前该方法不适用于原生镜像测试,因为这将需要将测试mock类弄到原生镜像中。

8. Test Bootstrap Configuration Options

There are a few system properties that can be used to tune the bootstrap of the test, specifically its classpath.

  • quarkus-bootstrap-offline - (boolean) if set by the user, depending on the value, will enable or disable the offline mode for the Maven artifact resolver used by the bootstrap to resolve the deployment dependencies of the Quarkus extensions used in the test. If the property is not set to any value, the artifact resolver will use the system’s default (user’s settings.xml).

  • quarkus-workspace-discovery - (boolean) controls whether the bootstrap artifact resolver should look for the test dependencies among the projects in the current workspace and use their output (classes) directories when setting up the classpath for the test to run. The default value is true.

  • quarkus-classpath-cache - (boolean) enables or disables the bootstrap classpath cache. With the number of the project dependencies growing, the dependency resolution will take more time which could at some point become annoying. The Quarkus bootstrap allows to cache the resolved classpath and store it in the output directory of the project. The cached classpath will be recalculated only after any of the pom.xml file in the workspace has been changed. The cache directory is also removed each time the project’s output directory is cleaned, of course. The default value is true.

9. Native Executable Testing

It is also possible to test native executables using @NativeImageTest. This supports all the features mentioned in this guide except injecting into tests (and the native executable runs in a separate non-JVM process this is not really possible).

This is covered in the Native Executable Guide.

quarkus.pro 是基于 quarkus.io 的非官方中文翻译站 ,最后更新 2020/04 。
沪ICP备19006215号-8
QQ交流群:1055930959
微信群: