使用 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)