如何在 GraphQL 和 Apollo 中部分模拟模式?

Posted

技术标签:

【中文标题】如何在 GraphQL 和 Apollo 中部分模拟模式?【英文标题】:How to partially mock a schema in GraphQL and Apollo? 【发布时间】:2019-04-17 17:11:41 【问题描述】:

我试图只模拟下面Contact 类型的一小部分。我的解析器从 REST 端点为 Contact 中的所有字段返回数据,test 除外。出于演示目的,我希望能够保留所有其他字段的服务器数据,但只模拟 test 字段。

我定义了以下 GraphQL 架构:

const typeDefs = `
    type Contact 
        id: String,
        first_name: String
        last_name: String
        middle_name: String
        date_of_birth: String
        test: String
    

    type Query 
        contacts: [Contact!]!
        Contact(id: String!): Contact!
    
`;

我定义了以下模拟:

const mocks = 
    Contact: () => (
        test: () => "This data is mocked!"
    )
;

并定义了以下解析器:

const resolvers = 
  Query: 
    contacts: async (parent, args,  dataSources ) =>
      dataSources.MYAPI.getAllContacts(),
    Contact: async (parent,  id ,  dataSources ) =>
      dataSources.MYAPI.getContact(id)
  
;

然后我初始化服务器:

const server = new ApolloServer(
  typeDefs,
  resolvers,
  mocks,
  dataSources: () => 
    return 
      MYAPI: new MYAPI()
    ;
  ,
  mockEntireSchema: false
);

以上行不通。我添加了mockEntireSchema:true 配置,它阻止了我的服务器响应被覆盖,但是test 属性仍然返回Hello World 的默认字符串模拟,而不是我尝试的This data is mocked! 模拟。

我知道模拟设置正确,因为我可以删除 mockEntireSchema 配置并且我的模拟数据正确显示。

这甚至可能吗?或者mockEntireSchema 和模拟的行为通常不支持这一点?

【问题讨论】:

同样的问题:在apollo-servergithub.com/apollographql/apollo-server/issues/2421上打开了一个问题 【参考方案1】:

根据documentation,您希望将mockEntireSchema 保留为false,并创建一个mocks 对象,其中包含您仍想模拟的组件。所有其他解析器将原样使用。但是,将使用您已定义的任何模拟,因此将永远不会使用返回 Contact 类型的查询解析器,因为您已将 Contact 定义为模拟。

【讨论】:

你描述的不是正在发生的事情。无论我使用mockEntireSchema 是真是假,Apollo 都会模拟所有“端点”。唯一的区别是,如果我选择mockEntireSchema: true,它会用我的模拟解析器覆盖现有的解析器。如果它是假的,它会忽略我提供的模拟解析器,转而支持现有的解析器,然后使用默认值(Hello world 等)进行模拟。【参考方案2】:

我还没有尝试过,但在我看来它应该可以工作(你所描述的)。但既然没有,一个可能的解决方法是为 test 字段添加一个字段解析器:

const resolvers = 
  Contact: 
    test: () => "This data is not mocked but the effect is the same!"
  ,
  Query: 
    contacts: async (parent, args,  dataSources ) =>
      dataSources.MYAPI.getAllContacts(),
    Contact: async (parent,  id ,  dataSources ) =>
      dataSources.MYAPI.getContact(id)
  
;

【讨论】:

【参考方案3】:

我现在相信这实际上是 Apollo https://github.com/apollographql/graphql-tools/issues/1114 中的一个错误。当您使用preserveResolvers: truemockEntireSchema: false(它们是相同的)时,它不会覆盖现有的解析器,但是,我根据我的模拟配置过滤掉了这些解析器,所以它们一开始就没有加载。

这使得部分模拟在原则上起作用。然而,错误是嵌套的 () => MockList(100) 调用在 graphql 包中引发错误,因为 graphql 将 MockList object 解释为“不可迭代”。 preserveResolvers: false 不会发生这种情况

【讨论】:

以上是关于如何在 GraphQL 和 Apollo 中部分模拟模式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 react-apollo graphql 查询中正确使用动态变量?

使用 Apollo 重新获取部分 GraphQL 查询的最佳实践?

如何在 apollo graphql 服务器中编写解析 graphql 过滤器

在 GraphQL 和 Apollo 中检索数组

身份验证Apollo Graphql for android

apollo (graphQL) - 如何在查询中发送对象数组