Consider the following 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
}
With it's corresponding resolver:
// 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 test file
// 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')
})
The field accountIdentifier
is mandatory and should throw a descriptive error message when it's missing in the request. However, the error thrown is:
"Network error: Response not successful: Received status code 400"
What is the correct way to modify the error message? I looked at type-graphql
with the class-validators and made sure that validate: true
is set but it doesn't give a descriptive error.
After checking the graphql playground, it does show the correct error message by default. The only question remaining is how write the jest test so it can read this message:
{
"error": {
"errors": [
{
"message": "Field AccountInput.accountIdentifier of required type String! was not provided.",
Thank you for any help you could give me.
The ApolloError
returned by your client wraps both the errors
returned in the response and any network errors encountered while executing the request. The former is accessible under the graphQLErrors
property, the latter under the networkError
property. Instea dof using toThrowError
, you should use toMatchObject
instead:
const expectedError = {
graphQLErrors: [{ message: 'the accountIdentifier is missing' }]
}
await expect(client.mutate(...)).rejects.toMatchObject(expectedError)
However, I would suggest avoiding using Apollo Client for testing. Instead, you can execute operations directly against your schema.
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)