使用 graphql 和 apollo 引发描述性错误
Posted
技术标签:
【中文标题】使用 graphql 和 apollo 引发描述性错误【英文标题】:throw a descriptive error with graphql and apollo 【发布时间】:2020-10-14 10:33:31 【问题描述】:考虑以下类:
// 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
字段是必填字段,当请求中缺少该字段时,应抛出描述性错误消息。但是,抛出的错误是:
“网络错误:响应不成功:收到状态码 400”
修改错误信息的正确方法是什么?我查看了type-graphql
和class-validators,并确保设置了validate: true
,但它没有给出描述性错误。
编辑
在检查了 graphql playground 之后,默认情况下它确实显示了正确的错误消息。剩下的唯一问题是如何编写笑话测试以便它可以读取此消息:
"error":
"errors": [
"message": "Field AccountInput.accountIdentifier of required type String! was not provided.",
感谢您能给我的任何帮助。
【问题讨论】:
【参考方案1】:您的客户端返回的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)
【讨论】:
感谢您的回答,但您收到的建议开玩笑是“graphQLErrors”:Array [],而不是graphql Playground 中可见的错误消息。使用正确的错误消息对象更新了 OP。根据您的建议,我将尝试将我的代码转换为不使用apollo-client
。
@DarkLite1 对不起,我忘了提到这里的另一个问题是您发送的查询实际上是无效的(这就是 400 状态所表示的)。您可以检查错误对象上networkError
属性的值以确定原因。
最后一个问题:不使用apollo-client
有什么好处吗?你为什么这么建议?
如果您有一个 GraphQL API,您想要测试的是来自该 API 的响应,而不一定是任何一个客户端如何使用该响应。
真的!并且直接使用graphql
也更干净。只剩下一个问题,符合我对这个错误对象的开玩笑期望` [GraphQLError: Field AccountInput.accountIdentifier of required type String!没有提供。],`。似乎无法正确使用语法。以上是关于使用 graphql 和 apollo 引发描述性错误的主要内容,如果未能解决你的问题,请参考以下文章
Apollo GraphQL Android 无法解决“无法解析 http 响应”错误