How to unit test express-graphql mutations?
Asked Answered
B

1

7

I have an Express-GraphQL API with a query and a mutation which works in GraphiQL, unit tests of query works, but a unit test of mutation returns a 405 error. my GraphQL schema is as follows:

type Subject {
  type: String
}

type Category {
  name: String
}

type SubjectCategories {
  subject: Subject
  categories: [Category]
}

type Query {
    subjectCategories(subjectType: String!): SubjectCategories
}

type Mutation {
    addSubjectCategory(subjectType: String! categoryName: String!): SubjectCategories
}

for simplifying this question, the implementation of these methods just echo back:

echoGetSubjectCategory({subjectType}, context) {
    const subject = new Subject(subjectType);
    const category = new Category("blah");
    const retval = {
      subject,
      categories: [category],
    };
    return retval;
}
echoMutateSubjectCategory({subjectType, categoryName}, context) {
    const subject = new Subject(subjectType);
    const category = new Category(categoryName);
    const retval = {
      subject,
      categories: [category],
    };
    return retval;
}

via Graphiql, everything works:

mutation {
  addSubjectCategory(subjectType: "s1" categoryName: "c1"){
    subject {
      type
    }
    categories {
      name
    }
  }
}

yields

{
  "data": {
    "addSubjectCategory": {
      "subject": {
        "type": "s1"
      },
      "categories": [
        {
          "name": "c1"
        }
      ]
    }
  }
}

and

{
 subjectCategories(subjectType: "s1"){
    subject {
      type
    }
    categories {
      name
    }
  }
}

yields the same.

in my API unit tests (using request from 'supertest-as-promised'), the query returns 200

const req = request(app)
      .get('/graphql')
      .set('Content-Type', 'application/json')
      .set('Accept', 'application/json')
      .send(JSON.stringify({
        query: "query {subjectCategories(subjectType: \"categorized\" ) { subject {type } categories {name} } }",
      }));
const res = await req;
expect(res.statusCode).toBe(200);

but this test fails:

const req = request(app)
  .get('/graphql')
  .set('Content-Type', 'application/json')
  .set('Accept', 'application/json')
  .send(JSON.stringify({
    query: "mutation {addSubjectCategory(subjectType: \"categorized\" categoryName: \"Politics\" ) { subject {type } categories {name} } }",
  }));
const res = await req;
expect(res.statusCode).toBe(200);

the mutation returns 405 the error message is very opaque:

Expected value to be (using ===):
      200
    Received:
      405
at Object.<anonymous> (test/api.test.js:171:28)
      at Generator.next (<anonymous>)
  at step (test/api.test.js:7:368)
  at test/api.test.js:7:528
      at <anonymous>

So how can I form this json payload to make this unit test of express-graphql pass ?

Bryozoan answered 22/10, 2017 at 9:6 Comment(0)
O
11

Queries can be made using both GET and POST requests, while mutations can only be made with POST requests.

Modify your code like this and it should work:

const req = request(app)
  .post('/graphql')
  .set('Content-Type', 'application/json')
  .set('Accept', 'application/json')
  .send({
    query: "mutation {addSubjectCategory(subjectType: \"categorized\" categoryName: \"Politics\" ) { subject {type } categories {name} } }"
  });
const res = await req;
expect(res.statusCode).toBe(200);
Otherwhere answered 22/10, 2017 at 12:27 Comment(3)
Thank you for posting this code snippet... I had done mutation: 'mutation....' instead of query: 'mutation .....' >______<Saum
You can also pass a string literal for the query property so you don't have to escape any of the quotation marks (inverted commas).Chaos
You're life saver!Compass

© 2022 - 2024 — McMap. All rights reserved.