利用GraphQL的Schema快速创建一个模拟服务器
总结
由于以下原因,我正在使用GraphQL开发客户端,并且希望有一个模拟服务器。
-
- バックエンドの開発を待たずにGraphQLのSchemaベースで非同期でフロントエンドの開発を行いたい
- テスト用にAPIのモック
我想快速地建立一个漂亮的模拟服务器,所以我进行了一番调查。
想要制作的东西
我想制作一个能够自动生成类型安全的MSW处理程序和数据创建函数的方法,以实现对GraphQL Schema的正向操作。这样一来,即使Schema发生变化,Mock服务器也能够快速跟进,而且Mock服务器的维护也会更加容易。
大致介绍步骤
我將簡單地寫出下面所做的事情。
首先,假设有以下的GraphQL Schema和Query。
架构
type Query {
getUser(id: ID!): User
}
type User {
id: ID!
name: String!
email: String!
}
查询
query GetUser($id: String!) {
getUser(id: $id) {
id
name
email
}
}
1. 安装必要的软件包。
首先,需要安装必要的软件包。
npm install @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-msw graphql-codegen-typescript-mock-data msw
每个用途如下所示。
GraphQL Code Generator: GraphQLのschema等からいろいろ自動生成してくれるライブラリ
Mock Service Worker(msw): ネットワーク層でリクエストをインターセプトし、モックのレスポンスを返すことができるライブラリ
@graphql-codegen/typescript-msw: クライアントで定義したquery/mutationから型セーフなmswのhandlerを自動生成する
graphql-codegen-typescript-mock-data: Schemaからデータ自動生成するライブラリ
2. GraphQL Code Generator的配置
接下来,按照以下方式编写codegen.yml文件。
const config: CodegenConfig = {
overwrite: true
schema: "path/to/your/schema.graphql" // 適当な値を入れる
documents: '**/*.graphql', // 適当な値を入れる
generates:
/**
* その他のgeneratorsは省略
*/
'__generated__/mockHandlers.ts': {
plugins: [
'typescript',
'typescript-operations',
'@graphql-codegen/typescript-msw',
{
'graphql-codegen-typescript-mock-data': {
prefix: 'mock',
},
},
],
},
}
通过此配置,执行代码生成命令将会生成以下文件,其中包含了TS类型、MSW处理程序和模拟数据生成函数的相应内容。
import { graphql,ResponseResolver,GraphQLRequest,GraphQLContext } from’msw’
export type Maybe = T | null;
export type InputMaybe = Maybe ;
export type Exact = { [K in keyof T]:T[K]};
export type MakeOptional <T,K extends keyof T> = Omit <T,K> & { [SubKey in K]?Maybe <T[SubKey]>};
export type MakeMaybe <T,K extends keyof T> = Omit <T,K> & { [SubKey in K]:Maybe <T[SubKey]>};
export type MakeEmpty = { [_ in K]?never};
export type Incremental = T | { [P in keyof T]?P extends’ $fragmentName’ |’__ typename’?T[P]:never};
/ **所有内置和自定义标量,映射到其实际值* /
export type Scalars = {
ID:{ input:string; output:string;}
String:{ input:string; output:string;}
Boolean:{ input:boolean; output:boolean;}
Int:{ input:number; output:number;}
Float:{ input:number; output:number;}
};export type Query = {
__ typename?:’Query’;
getUser?:Maybe ;
};
export type QueryGetUserArgs = {
id:Scalars [‘ID’] [‘input’];
};
export type User = {
__ typename?:’User’;
电子邮件:Scalars [‘String’] [‘output’];
id:Scalars [‘ID’] [‘output’];
名称:Scalars [‘String’] [‘output’];
};
export type GetUserQueryVariables = Exact <{ id:Scalars [‘ID’] [‘input’]; }>;
export type GetUserQuery = { __ typename?:’Query’,getUser?:{ __ typename?:’User’,id:string,name:string,email:string} | null };
/ **
* @param resolver接受捕获请求并可能返回模拟响应的函数。
* @see https://mswjs.io/docs/basics/response-resolver
* @example
* mockGetUserQuery((req,res,ctx)=> {
* const {id} = req.variables;
* return res(
* ctx.data({getUser})
*)
*})
* /
export const mockGetUserQuery =(resolver:ResponseResolver ,GraphQLContext ,any>)=>
graphql.query <GetUserQuery,GetUserQueryVariables>(
‘GetUser’,
解析器
)
export const mockQuery =(覆盖?:Partial ):Query =》{
return {
getUser:覆盖&&覆盖.hasOwnProperty(’getUser’)?覆盖.getUser!:mockUser(),
};
};
export const mockUser =(覆盖?:Partial ):User =》{
return {
电子邮件:覆盖&&覆盖.hasOwnProperty(’email’)?覆盖.email!:’sunt’,
id:覆盖&&覆盖.hasOwnProperty(’id’)?覆盖.id!:’a5756f00-41a6-422a-8a7d-d13ee6a63750’,
名称:覆盖&&覆盖.hasOwnProperty(’name’)?覆盖.name!:’porro’,
};
};
3. 使用自动生成的代码。
接下来只需要将以下代码组合起来即可。
mockGetUserQuery: 自動生成されてたmswのハンドラー
mockUser: 自動生成されたダミーデータ作成関数
※ 虚拟数据创建函数可以自然地进行重写,并且还可以设置更加现实的值。
import { mockGetUserQuery, mockUser } from '__generated__/mockHandlers'
const handlers = [
mockGetUserQuery((req, res, ctx) => {
const { id } = req.variables;
return res(
// Schemaに応じて適当なデータが作成される
ctx.data({ mockUser() })
)
})
]
const worker = setupWorker(...handlers)