【问题标题】:throw a descriptive error with graphql and apollo使用 graphql 和 apollo 引发描述性错误
【发布时间】:2023-03-08 15:25:02
【问题描述】:

考虑以下类:

// 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-graphqlclass-validators,并确保设置了validate: true,但它没有给出描述性错误。

编辑

在检查了 graphql playground 之后,默认情况下它确实显示了正确的错误消息。剩下的唯一问题是如何编写笑话测试以便它可以读取此消息:

{
  "error": {
    "errors": [
      {
        "message": "Field AccountInput.accountIdentifier of required type String! was not provided.",

感谢您能给我的任何帮助。

【问题讨论】:

    标签: graphql apollo apollo-client apollo-server typegraphql


    【解决方案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!没有提供。],`。似乎无法正确使用语法。
    猜你喜欢
    • 2021-07-05
    • 2018-08-21
    • 2018-08-01
    • 2018-10-21
    • 2017-06-23
    • 2018-12-27
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多