GraphQL Yoga 测试指南:从基础到高级实践
2025-07-07 02:00:47作者:温玫谨Lighthearted
GraphQL Yoga 作为一款现代化的 GraphQL 服务器实现,提供了完善的测试支持,让开发者能够轻松验证 GraphQL API 的正确性。本文将全面介绍如何在 GraphQL Yoga 中进行高效测试,涵盖从基础查询到高级订阅测试的完整方案。
测试基础:内置 HTTP 模拟
GraphQL Yoga 最显著的测试优势在于其内置的 HTTP 请求模拟能力。通过 yoga.fetch
方法,开发者可以像发送真实 HTTP 请求一样测试服务器,而实际上这是完全在内存中模拟的进程内通信,既保证了测试效率又不失真实性。
import { createSchema, createYoga } from 'graphql-yoga'
const schema = createSchema({
typeDefs: /* GraphQL */ `
type Query {
greetings: String!
}
`,
resolvers: {
Query: {
greetings: () => 'Hello World!'
}
}
})
const yoga = createYoga({ schema })
// 测试查询
const response = await yoga.fetch('http://yoga/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: '{ greetings }'
})
})
高级测试工具:HTTP 执行器
对于更复杂的场景,特别是处理订阅(Subscription)和增量交付(@defer/@stream)协议时,推荐使用 @graphql-tools/executor-http
提供的 buildHTTPExecutor
工具函数。
安装与基本用法
首先安装必要的依赖:
npm install @graphql-tools/executor-http
然后创建执行器实例:
import { buildHTTPExecutor } from '@graphql-tools/executor-http'
const executor = buildHTTPExecutor({
fetch: yoga.fetch
})
查询和变更测试
使用执行器测试常规查询和变更操作:
const result = await executor({
document: parse(/* GraphQL */ `
query {
greetings
}
`)
})
// 验证单值结果
function assertSingleValue<TValue extends object>(
value: TValue | AsyncIterable<TValue>
): asserts value is TValue {
if (Symbol.asyncIterator in value) {
throw new Error('Expected single value')
}
}
assertSingleValue(result)
console.assert(result.data?.greetings === 'Hello World!')
订阅测试
订阅测试需要特殊处理,因为订阅返回的是事件流而非单次响应:
function assertStreamValue<TValue extends object>(
value: TValue | AsyncIterable<TValue>
): asserts value is AsyncIterable<TValue> {
if (!(Symbol.asyncIterator in value)) {
throw new Error('Expected stream value')
}
}
const result = await executor({
document: parse(/* GraphQL */ `
subscription {
counter
}
`)
})
assertStreamValue(result)
// 迭代处理订阅事件
let iterationCounter = 0
for await (const value of result) {
console.assert(value.data?.counter === iterationCounter + 1)
iterationCounter++
if (iterationCounter >= 2) break
}
类型安全的测试实践
结合 GraphQL Code Generator 可以实现完全类型安全的测试代码:
import { graphql } from './gql' // 生成的类型
const HelloWorldQuery = graphql(/* GraphQL */ `
query HelloWorld {
hello
}
`)
const result = await executor({
document: HelloWorldQuery
})
// result.data?.hello 现在是类型安全的
这种方式可以避免拼写错误和类型不匹配问题,显著提高测试代码的可靠性。
高级测试场景
对于需要更精细控制的测试场景,可以直接处理请求体和响应流:
自定义订阅事件处理
function eventStream<TType = unknown>(source: ReadableStream<Uint8Array>) {
return new Repeater<TType>(async (push, end) => {
const iterable = source[Symbol.asyncIterator]()
// 处理流数据...
})
}
const response = await yoga.fetch('http://yoga/graphql', {
method: 'POST',
body: JSON.stringify({
query: 'subscription { counter }'
})
})
for await (const executionResult of eventStream(response.body!)) {
// 处理每个订阅事件
}
测试最佳实践
- 隔离测试环境:每个测试用例应该使用独立的 Yoga 实例
- 模拟外部依赖:在测试中替换真实的外部服务调用
- 验证响应状态:除了数据内容,也要检查 HTTP 状态码
- 清理资源:特别是订阅测试,确保正确关闭连接
- 组合测试:结合单元测试和集成测试策略
通过以上方法,开发者可以构建全面可靠的 GraphQL API 测试套件,确保应用在各种场景下的稳定性和正确性。GraphQL Yoga 提供的测试工具链让这一过程变得简单而高效。