6

I am using graphql-tool to mock up data for testing.

I hope to simulate when I select a user, it opens a detail page and shows the user company info.

Query

const query = `
  query User($id: ID!) {
    user(id: $id) {
      id
      company
    }
  }
`;

Mock server

import { addMockFunctionsToSchema } from 'graphql-tools';
import casual from 'casual';

const allUserIds = ['u1', 'u2', 'u3'];

const mocks = {
  User: () => ({
    id: casual.random_element(allUserIds),
    name: casual.name,
    company: casual.company_name
  })
};

addMockFunctionsToSchema({ schema, mocks });

However, right now, when I query with argument id 'u1', it will return a random user id for example 'u2', which gives me a little trouble to show it in front end.

I thought I can do something like this below, but turns out I am wrong. user is undefined in the code below.

const mocks = {
  User: (user) => ({
    id: user.id || casual.random_element(allUserIds),
    name: casual.name,
    company: casual.company_name
  })
};

Is there a way to pass the query arguments in graphql-tools? Thanks

Hongbo Miao
  • 45,290
  • 60
  • 174
  • 267
  • You're probably better off using a collection of fake/mock objects or a mock data generator with a consistent seed if you'd like to see your test data persistent throughout testing. – Claire Lin Jan 29 '19 at 02:27
  • @ClaireLin thanks, I did try actually. But haven't figured out where I should use `casual.seed(123);`. First, I tried to put on top just after import, it does not have any effect. Then I tried to put in mocks like `const mocks = { User: () => { casual.seed(0); return { id: casual.random_element(allUserIds), ... } } };`, it will give me all users with same info. – Hongbo Miao Jan 29 '19 at 02:35

1 Answers1

3

It depends on how consistent you want the test data to be. If all you care about is that the id remains consistent with your query argument, here is what you can do:

const mocks = {
  Query: () => ({
    user: (root, user) => ({
      id: user.id || casual.random_element(allUserIds),
      name: casual.name,
      company: casual.company_name
    })
  })
};

As mentioned here in the documentation, mock functions are just like GraphQL resolvers. So the parameters of the functions follow the same order of root, arguments, context that are available for each field.

Please see the code sandbox here for a live demo.

This guarantees whenever you query user with id u1, you always receive a user data object with its id = "u1" with randomly generated company and name fields. However, if you want the entire user object to be persistent throughout a test, you'll need to create the mock user data outside mock functions and query and filter out data accordingly.

Claire Lin
  • 2,372
  • 8
  • 13
  • Thanks!! I missed that part document. I corrected a little bit since based on your old one `User: () => ({ id: (root, { id }) => id, ...`. When I try to use `id: (root, something) => id`, `something` will always be empty object, which makes `id` is undefined. When I moved it top like `User: (root, user) => ({ id: user.id || casual.random_element(allUserIds),` then it works. – Hongbo Miao Jan 29 '19 at 03:58
  • Ah you are right. I got confused with your query `User` and the type `User` with PascalCase. I'd suggest to follow the naming convention and rename the query to be camelCase `user` to reduce confusion. – Claire Lin Jan 29 '19 at 05:05
  • @HongboMiao I added a live demo and updated the code snippet here to clarify that `user` is in fact a `query`. – Claire Lin Jan 29 '19 at 05:34
  • Oh I did follow name conversion. I think you misunderstood my code in question. My `User` is under root mocks (same level with `Query`) which should be capitalized. It is for all `User` type used in all places GraphQL schema, not just in query. But anyway thanks for the direction! – Hongbo Miao Jan 29 '19 at 21:09