Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mock with Federations - Syntax Error: Unexpected Name "Hello" #348

Closed
vmptk opened this issue Sep 23, 2019 · 10 comments
Closed

Mock with Federations - Syntax Error: Unexpected Name "Hello" #348

vmptk opened this issue Sep 23, 2019 · 10 comments

Comments

@vmptk
Copy link

vmptk commented Sep 23, 2019

When using the '@apollo/federation' and ''@apollo/gateway' with mocked types and with micro server ('apollo-server-micro'). An error occurs on the gateway service:

Encountered error when loading images at http://localhost:4003/graphql: Syntax Error: Unexpected Name "Hello"

Expected behaviour is to properly build the graph and use mocked types.
Actual behaviour, gateway is failing to load the types.

A workaround is to set the option: mockEntireSchema: false,

@donedgardo
Copy link

are you using mock: true or passing in custom mocks?, Are you doing this in each mirco service or the gateway level service?

@schwarmco
Copy link

schwarmco commented Oct 18, 2019

I faced the same problem, when i wanted to mock federated services. When you use

  • mockEntireSchema: true (default) - the gateway will fail to start, because in GetServiceDefinition the _service will have mocked "Hello World"
  • mockEntireSchema: false - it works, but you can't "stub" out your resolvers anymore

So basically what i'm currently doing is:
[Code Snippet removed to avoid confusion]
It'd be great, if there would be a more elegant way - or maybe i'm missing something obvious, in that Mocking on Federation needs a different approach.

Edit:

After running into another problem, where extended type fields weren't mocked correctly, i now figured a way, that works for me quite well:

const schema = buildFederatedSchema([{ typeDefs, resolvers }])
if (process.env.USE_MOCKS) {
    addMockFunctionsToSchema({
        schema,
        mocks: require('./mocks'),
        preserveResolvers: true // so GetServiceDefinition works
    })
}

const server = new ApolloServer({ schema })

So, my bottomline is: don't use ApolloServers mock option, when doing federation.

@tzohpilotl
Copy link

@schwarmco but isn't using preserveResolvers: true overriding the provided mocks? In my experience, setting that to true would make your service use its original resolvers, therefore, defeating the purpose of using mocks in the first place.

@philippemiguet
Copy link

philippemiguet commented Jan 16, 2020

Hey there I'm facing the same issue here, I think it will be pretty common to anyone relying on mocking locally to improve developer experience and then try to use Federation.

I agree with @tzohpilotl, it defeats the purpose and reduce the power of the mocks option, which is one great feature to improve developper experience.

I've been digging in the code and the issue is the following: when providing a serviceList to the config, the Apollo Gateway will iterate on each of them to fetch the SDL and parse it into a typeDefs object (code). The gateway performs the following query to fetch the SDL (code):

query {
  _service {
    sdl
  }
}

When mocks: true is passed on a federated service, the above query will return an invalid SQL schema which the Apollo Gateway is unable to parse properly:

{
  "data": {
    "_service": {
      "sdl": "Hello World"
    }
  }
}

From there, I only see two potential paths:

  1. Find a way to return the SDL even when mock: true is passed.
  2. Use Apollo Graph Manager.

I think the second option is probably the way to go since when using AGM, the code will fetch the SDL from storage instead of hitting the federated service. (code)

I will report back with any finding by tomorrow since I'm actively looking for a solution to this issue :)

@philippemiguet
Copy link

philippemiguet commented Jan 16, 2020

  1. Find a way to return the SDL even when mock: true is passed.

I've been playing with the code and I've found a way to have Federation to work with a federated service using mock. Here is what you would need to do:

// First declare your schema as a separate const
const schemaString = `
  type User {
    _id: ID!
  }

  extend type Query {
    user(id: ID!): User
  }
`;

// Create type def of your string schema using the gql
const typeDefs = gql(schemaString);

// Create mock of the _Service type which will be used by the Apollo Gateway to fetch your schema definition
const mocks = {
  _Service: () => ({
    'sdl': schemaString
  }),
};

const options = {
  typeDefs,
  resolvers,
  mocks,
};

const server = new ApolloServer(options);
  1. Use Apollo Graph Manager.

Tomorrow I will attempt to use Apollo Graph Manager instead of passing a serviceList. It feels a cleaner solution to me.

In the meantime, I hope this temporary solution will unblock you all :)

@philippemiguet
Copy link

  1. Use Apollo Graph Manager.

Confirming that using AGM to manage your graph will then allow you to start federated services with the mocks option as you would usually 👍

@abernix abernix transferred this issue from apollographql/apollo-server Jan 15, 2021
@nemisj
Copy link

nemisj commented Feb 1, 2021

  1. Find a way to return the SDL even when mock: true is passed.

I've been playing with the code and I've found a way to have Federation to work with a federated service using mock. Here is what you would need to do:

// First declare your schema as a separate const
const schemaString = `
  type User {
    _id: ID!
  }

  extend type Query {
    user(id: ID!): User
  }
`;

// Create type def of your string schema using the gql
const typeDefs = gql(schemaString);

// Create mock of the _Service type which will be used by the Apollo Gateway to fetch your schema definition
const mocks = {
  _Service: () => ({
    'sdl': schemaString
  }),
};

const options = {
  typeDefs,
  resolvers,
  mocks,
};

const server = new ApolloServer(options);
  1. Use Apollo Graph Manager.

Tomorrow I will attempt to use Apollo Graph Manager instead of passing a serviceList. It feels a cleaner solution to me.

In the meantime, I hope this temporary solution will unblock you all :)

There is also string based query available on typeDefs, so that you do not need declare your schema as separate variable:

const mocks = {
  _Service: () => ({
    'sdl': typeDefs?.loc?.source?.body
  }),
};

@kevin-lindsay-1
Copy link

I had this issue recently, just set the following on the federated service:

new ApolloServer({
  ...,
  mockEntireSchema: false,
  mocks: {},
})

And had the gateway use as normal.

@namirsab
Copy link

Hey!
This issue is still opened, so I guess there is no real solution for it? Are there any news?

@trevor-scheer
Copy link
Member

Closed via #1773

#1773 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants