You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

graphql-js订阅集成测试异常:GraphiQL正常但测试失败

我帮你梳理下几个关键问题,一个个来解决:

问题分析与修复方案

1. 集成测试中execGraphQL未初始化,导致Mutation根本没执行

看你的测试代码,let execGraphQL;之后直接调用await execGraphQL(...),但这个变量完全没赋值,会直接抛出TypeError: execGraphQL is not a function,Mutation都没跑,订阅自然收不到正确的payload。

修复代码:
用chai-http实现一个发送GraphQL请求的方法:

execGraphQL = async (query) => {
  return chai.request(server)
    .post('/graphql')
    .send({ query });
};

然后再调用await execGraphQL(...)执行Mutation。

2. Apollo Client配置混用新旧API,导致订阅链路异常

你同时设置了旧版的networkInterface和新版的link,这会让Apollo Client的网络层逻辑混乱,无法正确接收订阅事件。在Apollo Client 2.x+版本,应该用WebSocketLink和HttpLink组合,通过split区分订阅和查询/突变的请求链路。

修复代码:

const { WebSocketLink } = require('apollo-link-ws');
const { split } = require('apollo-link');
const { getMainDefinition } = require('apollo-utilities');

// 创建WebSocket链接处理订阅
const wsLink = new WebSocketLink({
  uri: GRAPHQL_ENDPOINT,
  options: { reconnect: true },
  webSocketImpl: ws
});

// 创建HTTP链接处理查询和突变
const httpLink = new HttpLink({ uri: 'http://localhost:3000/graphql' });

// 自动选择请求链路:订阅用WS,其他用HTTP
const link = split(
  ({ query }) => {
    const definition = getMainDefinition(query);
    return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
  },
  wsLink,
  httpLink
);

// 初始化Apollo Client
apollo = new ApolloClient({
  link,
  cache: new InMemoryCache()
});

3. 订阅的filter函数里错误调用pubSub.subscribe

你在withFilter的过滤逻辑里调用了pubSub.subscribe(info.fieldName, null, subscriptionPayload),这完全是逻辑错误——pubSub.subscribe是服务端用来订阅事件的方法,而这里的subscribe函数本身就是处理客户端订阅的入口,filter函数只负责判断是否要把当前payload推给客户端,不该在这里做订阅操作,这会导致事件订阅混乱,返回错误的payload。

修复方案:
直接删除这行代码,只保留过滤逻辑(如果需要的话):

subscribe: withFilter(
  () => pubSub.asyncIterator(modelName),
  (payload, variables, context, info) => {
    // 这里只做过滤判断,比如匹配创建/更新/删除操作
    const { create } = variables.input;
    // 假设你的payload里有action字段标识操作类型,按需调整
    // return create && payload.action === 'CREATE';
    return true; // 先保持返回true,确保能收到数据
  }
),

4. 订阅resolve函数的字段映射错误

你的订阅查询里是Customer { customer { name } },但resolve函数返回的是object: payload.data,这会导致客户端拿到的customer字段为undefined。另外,clientSubscriptionId应该从客户端传入的args.input里取,而不是从服务端发布的payload里拿。

修复代码:

resolve(payload, args, context, info) {
  // 从客户端订阅参数里取clientSubscriptionId
  const { clientSubscriptionId } = args.input;
  const { object } = payload; // 服务端发布的事件数据
  const where = object?.where;
  const type = object?.type;
  const target = object?.target;

  return Promise.resolve(subscribeAndGetPayload(payload, args, context, info))
    .then(result => ({
      clientSubscriptionId,
      where,
      type,
      target,
      customer: result.data, // 和查询里的字段名保持一致
    }));
}

5. 调整测试断言逻辑

修复完以上问题后,订阅收到的payload结构会是:

{
  data: {
    Customer: {
      customer: { name: "Atif 21" }
    }
  }
}

所以测试断言要改成:

const result = await subscriptionPromise;
expect(result.data.Customer.customer.name).to.equal("Atif 21");

内容的提问来源于stack exchange,提问作者M Atif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:29:46