测试

DGS 框架允许你写轻量级的测试,可以针对运行需求,部分启动框架。

例子

在写测试之前,请确认启用了 JUnit。如果你是通过 Spring Initializr 来创建的工程项目,那么这个配置是默认准备好的。

Gradle:

dependencies {
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

Gradle Kotlin:

tasks.withType<Test> {
    useJUnitPlatform()
}

Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

用以下的内容创建测试类,用来测试来自 getting startedShowsDatafetcher

Java:

Kotlin:

使用 @SpringBootTest 注解将其变成一个 Spring 测试。如果你没有明确指定 classes ,Spring 将会启动在 classpath 中的所有组件。这样对一个比较小的项目而言,还可以接受,但是对于一个拥有很多“消耗很大”组件的项目来说,明确的添加我们所需要的测试类,将会加速测试。这样的话,我们需要将 DGS 框架配置类 DgsAutoConfiguration 以及需要测试的类 ShowsDatafetcher 添加进来。

为了执行查询,我们需要在测试中注入 DgsQueryExecutor。这个接口有很多可以执行查询并返回结果的方法。它将在 /graphql 端点上执行准确的查询代码,你不需要在测试中去处理 HTTP 相关的内容。这个 DgsQueryExecutor 方法接收 JSON paths,以至于你可以更容易准确的从响应中抽取你需要的数据。DgsQueryExecutor 也包含了一些方法(例如:executeAndExtractJsonPathAsObject),通过底层的 Jackson,将结果反序列化成 Java 对象。开源组件 JsonPath libraryarrow-up-right 将为 JSON paths 提供支撑。

写更多的测试,比如验证使用了titleFilterShowsDatafetcher 的行为。你可以在 IDE 中执行这些测试,或者像其他 JUnit 测试一样,通过 Gradle/Maven 来执行。

为测试创建 GraphQL Queries

之前的例子中,我们手写了查询字符串。这对于很小很直接的查询是足够简洁的。然而,构造一个长查询字符串是非常让人厌烦的,尤其是在没有多行字符串支持的 Java 中。正因为此,我们可以使用 GraphQLQueryRequest 与生成用于构建请求所需要的类的 code generation 插件组合去创建一个 GraphQL request。这将是一个方便且类型安全的构建查询的方式。

请按照 here 的指导搭建代码生成器,用于生成创建查询所必须的类。

现在,我们可以使用 GraphQLQueryRequest 去创建查询并且使用 GraphQLResponse 来抽取响应数据。

Java:

Kotlin:

作为 graphql-client module 一部分的 GraphQLQueryRequest 已经可以用于创建查询字符串,并且可以分别包装在响应中。你可以参考 GraphQLClient JavaDoc 获取更多支持方法的细节。

在测试中 Mocking 外部服务调用

一个 data fetcher 连接外部服务(比如:数据库 或者 gRPC 服务)是非常正常的情况。如果需要将这样的情况包含在测试中,将会增加以下两个问题:

  1. 潜在因素:当你的业务包含很多外部请求的时候,测试将会执行得很慢。

  2. 疑问:你的代码有 Bug 了?还是外部系统出现异常了?

大多数情况,我们最好 Mock 这些外部调用。Spring 已经有了一个非常好的支撑,就是 @Mockbean 注解,我们可以在 DGS 的测试中利用这个注解。

例子

我们更新一下 Shows 的那个例子,让它从外部数据源中加载数据,而不是之前那样返回一个固定列表。这个例子的目的仅仅是将一个固定列表改成了一个新的带有 @Service 注解的类。data fetcher 需要更新注入这个 ShowsService

Java:

Kotlin:

目前来说,现在这个例子的数据还是来源于内存,想象一下,这个 Service 真的去调用了一个外部的数据存储。我们一起尝试在测试中 Mock 这个 Service。

Java:

Kotlin:

测试异常

至今为止,你写的都是正常测试。失败场景也很容易测试。我们使用之前 Mocked 例子来强制抛出一个异常。

Java:

Kotlin:

当在执行查询的时候,发生了错误,这些错误将会包装在一个 QueryException 中。你可以很容易的查看这些错误。QueryException 中的 message 关联了所有错误。你可以通过 getErrors() 方法来进一步的检查错误。

最后更新于

这有帮助吗?