【问题标题】:Pass createReadStream within GraphQL mutation (jest test purposes)在 GraphQL 突变中传递 createReadStream(开玩笑的测试目的)
【发布时间】:2021-07-11 07:29:06
【问题描述】:

我正在努力在突变查询中传递 createReadStream。

我所做的是用 Jest 模拟如下

const createReadStream = jest.fn();

我就是这样用的

file: {
  filename: "Marvel (1).pdf",
  mimetype: "application/pdf",
  encoding: "7bit",
  createReadSteam: ${createReadStream}
}

这是完整的代码

import { initResources } from 'jeto';
import { graphql } from 'graphql';
import { prop, path } from 'ramda';
import initServices from '../services';
import initHttp from '../init/http';
import initModels from '../init/models';
import initConfig from './initConfig';
import initDatabase from '../init/database';
import initRouter from '../init/router';
import initDataLoaders from '../dataLoaders';
import initApollo from '../init/apollo';
import api from '../../lib/api';
import { ROLE } from '../../lib/models/people';
import { login } from './utils';
// import { resumes } from './utils/resumesTests';
// import { userAdmin, userHeadHunter, userSales, userWorker } from './utils/usersTests';

let MONGO;
let SERVER;
let runql;
let CTX;
let GCTX;
let PROFILE;
const TENANT = { key: 'TENANT' };

describe('server | graphql | Resumes', () => {
  beforeAll(async () => {
    const resources = [
      initConfig,
      initDatabase,
      initModels,
      initDataLoaders,
      initServices,
      initApollo,
      initRouter,
      initHttp,
    ];

    return initResources(resources)
      .then(async ctx => {
        CTX = ctx;
        const { httpServer, mongo, models } = ctx();
        MONGO = mongo;
        SERVER = httpServer;
        const tenantId = await models.tenants.collection.insertOne(TENANT).then(prop('insertedId'));
        TENANT._id = tenantId;
        api.config({ endpoint: httpServer.url, tenant: TENANT.key });
        const { user } = await login(models, TENANT, [ROLE.admin]);
        GCTX = {
          user,
          ctx: CTX,
          models: CTX().models(user, { authRequired: true, ...TENANT }),
          dataLoaders: CTX().dataLoaders,
        };
        runql = async query => {
          console.log('query', query);

          const res = await graphql(CTX().apollo.schema, query, null, GCTX);
          console.log('res', res);

          if (res.errors) throw res.errors[0];
          return res;
        };
      })
      .catch(() => {
        if (MONGO) {
          MONGO.database.dropDatabase();
          MONGO.close();
        }
      });
  });

  afterAll(() => {
    return MONGO.database
      .dropDatabase()
      .then(() => SERVER.close())
      .then(() => MONGO.close());
  });

  it('should add resumes', async () => {
    const createReadStream = jest.fn();
    const query = `
    mutation {
        createResume(
            status: checking,
            firstname: "Mathieu",
            lastname: "Chedid",
            email: "mchedid@gmail.com",
            phoneNumber: "+33 9 49 48 50 54",
            rating: 5,
            seniority: 6,
            hardSkills: ["6048d850735ec00ec36db0d9", "6048d850735ec00ec36db0c4", "6048d850735ec00ec36db0b8"],
            softSkills: [],
            comment: "",
            file: {
                filename: "Marvel (1).pdf",
                mimetype: "application/pdf",
                encoding: "7bit",
                createReadSteam: ${createReadStream}
            }
        ){ _id } }`;

    PROFILE = await runql(query).then(path(['data', 'createResume']));

    expect(PROFILE._id).toBeDefined();
  });

控制台日志

GraphQLError [Object]: Syntax Error: Expected Name, found "(".

当我摆脱

  createReadSteam: ${createReadStream}

从文件中重新开始测试,我可以在控制台中观察到这一点

Error: ‘Upload’ scalar literal unsupported.

【问题讨论】:

    标签: javascript jestjs graphql


    【解决方案1】:

    第一个:变异参数应始终作为变量传递 https://graphql.org/learn/queries/#variables -

    实际上不可能在查询中传递硬编码的文件/上传!

    第 2:graphQL 上传通常实现为 specs 中描述的两步过程:

    • 预处理 - 使用带有operations 的经典POST multipart form-data 编码数据集发出请求(包含graphql "query" 和稍后处理的args - 突变加上"variables" - 非文件和空文件 args)、map(用于查询变量映射的文件)和文件
    • 传递给正常处理的查询(变异)得到更新"variables",文件变量现在是Upload 标量(取决于实现)- 带有名称的对象,上传的文件/流句柄。李>

    对于第二步测试,请遵循“正常”node.js [上传] 文件/流模拟

    已经回答的解决方案here

    【讨论】:

      【解决方案2】:

      正如@xadm 提到的,解决方案是将上传的文件添加到查询旁边,并修改 runql 方法以添加参数 -> 变量

      it('should add a resume', async () => {
          const stream = Readable.from(Buffer.from('coucou'));
          const query = `
            mutation 
              createResume($file: Upload)
                { 
                  createResume(
                      file: $file,
                      firstname: "mathieu",
                      lastname: "chedid",
                      email: "mchedid@gmail.com",
                      phoneNumber: "+33 6 17 82 54 08"
                      status: pending,
                      seniority: 1,
                      hardSkills: ["6048d850735ec00ec36db0d9"] 
                  ) { _id, firstname } 
                } 
          `;
          const file = Promise.resolve({
            createReadStream: () => stream,
            stream,
            filename: './resume.pdf',
            mimetype: `application/pdf`,
          });
          RESUME = await runql(query, { file }).then(path(['data', 'createResume']));
          expect(RESUME._id).toBeDefined();
          expect(RESUME.firstname).toEqual('mathieu');
        });
      
      runql = async (query, variables = {}) => {
          const res = await graphql(CTX().apollo.schema, query, null, GCTX, variables);
          if (res.errors) throw res.errors[0];
          return res;
      };
      

      【讨论】:

        猜你喜欢
        • 2021-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        • 1970-01-01
        • 2022-11-18
        • 2020-02-06
        相关资源
        最近更新 更多