使用 graphql 和 apollo 抛出描述性错误
throw a descriptive error with graphql and apollo
考虑以下 class:
// entity/Account.ts
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, Index, CreateDateColumn, UpdateDateColumn } from 'typeorm'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
@Entity()
export class Account extends BaseEntity {
@Field(() => Int)
@PrimaryGeneratedColumn()
id: number
@Field()
@Column({ length: 50, unique: true })
@Index({ unique: true })
accountIdentifier: string
@Field({ nullable: true })
@Column({ length: 100 })
name?: string
}
与其对应的解析器:
// AccountResolver.ts
@Resolver()
export class AccountResolver {
@Mutation(() => Account)
async addAccount(@Arg('options', () => AccountInput) options: AccountInput) {
try {
// if (!options.accountIdentifier) {
// throw new Error(`Failed adding account: the accountIdentifier is missing`)
// }
return await Account.create(options).save()
} catch (error) {
if (error.message.includes('Cannot insert duplicate key')) {
throw new Error(
`Failed adding account: the account already exists. ${error}`
)
} else {
throw new Error(`Failed adding account: ${error}`)
}
}
}
}
Jest 测试文件
// AccountResolver.test.ts
describe('the addAccount Mutation', () => {
it('should throw an error when the accountIdentifier is missing', async () => {
await expect(
client.mutate({
mutation: gql`
mutation {
addAccount(
options: {
name: "James Bond"
userName: "James.Bond@contoso.com"
}
) {
accountIdentifier
}
}
`,
})
).rejects.toThrowError('the accountIdentifier is missing')
})
字段 accountIdentifier
是必填字段,当请求中缺少该字段时,应抛出描述性错误消息。然而,抛出的错误是:
"Network error: Response not successful: Received status code 400"
修改错误信息的正确方法是什么?我用 class-validators 查看了 type-graphql
并确保设置了 validate: true
但它没有给出描述性错误。
编辑
检查 graphql playground 后,它确实默认显示正确的错误消息。剩下的唯一问题是如何编写笑话测试以便它可以读取此消息:
{
"error": {
"errors": [
{
"message": "Field AccountInput.accountIdentifier of required type String! was not provided.",
谢谢你能给我的任何帮助。
客户端返回的 ApolloError
包含响应中返回的 errors
和执行请求时遇到的任何网络错误。前者在graphQLErrors
属性下可访问,后者在networkError
属性下可访问。 Instea dof 使用 toThrowError
,你应该使用 toMatchObject
代替:
const expectedError = {
graphQLErrors: [{ message: 'the accountIdentifier is missing' }]
}
await expect(client.mutate(...)).rejects.toMatchObject(expectedError)
但是,我建议避免使用 Apollo Client 进行测试。相反,您可以直接针对您的架构执行操作。
import { buildSchema } from 'type-graphql'
import { graphql } from 'graphql'
const schema = await buildSchema({
resolvers: [...],
})
const query = '{ someField }'
const context = {}
const variables = {}
const { data, errors } = await graphql(schema, query, {}, context, variables)
考虑以下 class:
// entity/Account.ts
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, Index, CreateDateColumn, UpdateDateColumn } from 'typeorm'
import { Field, Int, ObjectType } from 'type-graphql'
@ObjectType()
@Entity()
export class Account extends BaseEntity {
@Field(() => Int)
@PrimaryGeneratedColumn()
id: number
@Field()
@Column({ length: 50, unique: true })
@Index({ unique: true })
accountIdentifier: string
@Field({ nullable: true })
@Column({ length: 100 })
name?: string
}
与其对应的解析器:
// AccountResolver.ts
@Resolver()
export class AccountResolver {
@Mutation(() => Account)
async addAccount(@Arg('options', () => AccountInput) options: AccountInput) {
try {
// if (!options.accountIdentifier) {
// throw new Error(`Failed adding account: the accountIdentifier is missing`)
// }
return await Account.create(options).save()
} catch (error) {
if (error.message.includes('Cannot insert duplicate key')) {
throw new Error(
`Failed adding account: the account already exists. ${error}`
)
} else {
throw new Error(`Failed adding account: ${error}`)
}
}
}
}
Jest 测试文件
// AccountResolver.test.ts
describe('the addAccount Mutation', () => {
it('should throw an error when the accountIdentifier is missing', async () => {
await expect(
client.mutate({
mutation: gql`
mutation {
addAccount(
options: {
name: "James Bond"
userName: "James.Bond@contoso.com"
}
) {
accountIdentifier
}
}
`,
})
).rejects.toThrowError('the accountIdentifier is missing')
})
字段 accountIdentifier
是必填字段,当请求中缺少该字段时,应抛出描述性错误消息。然而,抛出的错误是:
"Network error: Response not successful: Received status code 400"
修改错误信息的正确方法是什么?我用 class-validators 查看了 type-graphql
并确保设置了 validate: true
但它没有给出描述性错误。
编辑
检查 graphql playground 后,它确实默认显示正确的错误消息。剩下的唯一问题是如何编写笑话测试以便它可以读取此消息:
{
"error": {
"errors": [
{
"message": "Field AccountInput.accountIdentifier of required type String! was not provided.",
谢谢你能给我的任何帮助。
客户端返回的 ApolloError
包含响应中返回的 errors
和执行请求时遇到的任何网络错误。前者在graphQLErrors
属性下可访问,后者在networkError
属性下可访问。 Instea dof 使用 toThrowError
,你应该使用 toMatchObject
代替:
const expectedError = {
graphQLErrors: [{ message: 'the accountIdentifier is missing' }]
}
await expect(client.mutate(...)).rejects.toMatchObject(expectedError)
但是,我建议避免使用 Apollo Client 进行测试。相反,您可以直接针对您的架构执行操作。
import { buildSchema } from 'type-graphql'
import { graphql } from 'graphql'
const schema = await buildSchema({
resolvers: [...],
})
const query = '{ someField }'
const context = {}
const variables = {}
const { data, errors } = await graphql(schema, query, {}, context, variables)