从10月8日至10日加入我们在纽约市的聚会,了解关于 GraphQL 联邦和 API 平台工程的最新技巧、趋势和新闻。加入2024年纽约市的 GraphQL 大会
文档
免费开始
您正在查看此软件旧版本的文档。 切换到最新稳定版本。

数据构建者(实验性)


⚠️ 数据构建者是实验性的,可能发生变化。如果您对它们有任何反馈,请通过GitHub问题Kotlin Slack社区提出。

为您生成模型和解析器,以从您的网络响应中创建这些模型的实例。然而,在测试或其他场合,有时手动使用已知值实例化模型非常有用。这样做并不像看上去那么简单,尤其是当使用 时。operationBased 模型需要实例化每个 ,以及为每个复合类型选择一个合适的 __typename。数据构建器通过提供与 Json 结构匹配的构建器,使这个过程变得更简单。

注意:Apollo Kotlin 的早期版本使用了测试构建器。数据构建器是测试构建器的一个简化版本,同时与自定义标量也更兼容。如果您正在寻找测试构建器的文档,它仍然可以在 这里 找到。

启用数据构建器

要启用数据,将 generateDataBuilders 选项设置为 true

build.gradle[.kts]
apollo {
service("service") {
// ...
// Enable data builder generation
generateDataBuilders.set(true)
}
}

这将为您模式中的每个复合类型生成构建器,以及为您的每个操作生成一个辅助函数 Data {}

示例用法

假设我们正在构建一个使用以下 的模拟结果的测试:

query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
firstName
lastName
age
ship {
model
speed
}
friends {
firstName
lastName
}
... on Droid {
primaryFunction
}
... on Human {
height
}
}
}

以下是如何使用对应的模拟结果数据构建器:

@Test
fun test() {
val data = HeroForEpisodeQuery.Data {
// Set values for particular fields of the query
hero = buildHuman {
firstName = "John"
age = 42
friends = listOf(
buildHuman {
firstName = "Jane"
},
buildHuman {
lastName = "Doe"
}
)
ship = buildStarship {
model = "X-Wing"
}
}
}
assertEquals("John", data.hero.firstName)
assertEquals(42, data.hero.age)
}

在这个例子中,hero 是一个具有指定 firstNameage 值的 Human 对象。对于 lastNameheight,将自动填充模拟值。同样,飞船的速度、第一位朋友的姓氏和第二位朋友的名字的值也将自动填充。

您可以将上面的 buildHuman 替换为 buildDroid 来创建一个 Droid 对象。

别名

由于数据生成器是 schema-based,而 在您的查询中定义,因此代码生成器无法生成针对这些字段的 。相反,您需要显式指定它们。

给定如下 查询:)

query GetHeroes {
luke: hero(id: "1002") {
name
}
leia: hero(id: "1003") {
name
}
}

您可以这样生成一个模拟数据模型

val data = GetHeroes.Data {
this["luke"] = buildHumanHero {
name = "Luke"
}
this["leia"] = buildHumanHero {
name = "Leia"
}
}

@skip@include 指令

默认情况下,数据生成器与您的 schema 中的类型匹配。如果一个 字段是非空白的,您将不得不提供一个值或将默认 提供的一个值。对于 @skip@include 指令来说这是一个问题,因为即使在非空的情况下,字段也可能不存在。为了考虑这种情况,使用与 相同的语法。

query Skip($skip: Boolean!) {
nonNullableInt @skip(if: $skip)
}

您可以这样生成一个模拟数据模型

val data = SkipQuery.Data {
this["nonNullableInt"] = Optional.Absent
}
assertNull(data.nonNullableInt)

配置默认字段值

为了将默认值分配给 字段,数据生成器使用 FakeResolver 接口的某个实现。默认情况下,它们使用 DefaultFakeResolver 的一个实例。

DefaultFakeResolver 给每个 String 字段 的默认值是该字段的名称,并在分配默认值给 Int 字段时递增计数器。它为其他类型定义了类似的行为。

您可以使用自己的 own FakeResolver 实现(可选地委托给 DefaultTestResolver 以获得先行优势)。然后,您可以将这个实现作为参数传递给 Data 函数,如下所示:

// A TestResolver implementation that assigns -1 to all Int fields
class MyFakeResolver : FakeResolver {
private val delegate = DefaultFakeResolver(__Schema.all)
override fun resolveLeaf(context: FakeResolverContext): Any {
return when (context.mergedField.type.leafType().name) {
"Int" -> -1 // Always use -1 for Ints
else -> delegate.resolveLeaf(context)
}
}
override fun resolveListSize(context: FakeResolverContext): Int {
// Delegate to the default behaviour
return delegate.resolveListSize(context)
}
override fun resolveMaybeNull(context: FakeResolverContext): Boolean {
// Never
return false
}
override fun resolveTypename(context: FakeResolverContext): String {
// Delegate to the default behaviour
return delegate.resolveTypename(context)
}
}
@Test
fun test() {
val data = HeroForEpisodeQuery.Data(resolver = myTestResolver) {
hero = buildHuman {
firstName = "John"
}
}
// Unspecified Int field is -1
assertEquals(-1, data.hero.age)
}
上一页
模拟 GraphQL 响应
下一页
UI 测试
评价文章评价在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,经营Apollo GraphQL。

隐私政策

公司