OpenAPI 定義を正本として、WireMock 実行資産(mappings/ と __files/)を機械生成する CLI ツールです。
OpenAPI
+ case YAML
+ responses-root/(レスポンス JSON)
↓
oapi2wire
↓
wiremock-out/
├─ mappings/
└─ __files/
↓
WireMock
OpenAPI を正本としつつ、返し分け条件(パスパラメータ・クエリパラメータ・JSON ボディ)を case YAML で定義することで、柔軟なモック資産を生成します。
go install github.com/ramsesyok/oapi2wire@latestバージョンを固定して利用する場合:
go install github.com/ramsesyok/oapi2wire@v0.2.0または、ソースからビルド:
git clone https://github.com/ramsesyok/oapi2wire.git
cd oapi2wire
go build -o oapi2wire .oapi2wire init \
--openapi ./openapi.yaml \
--out-cases ./mock-cases.yaml \
--responses-root ./mock-responses \
--tags petOpenAPI の各 operationId に対して case YAML テンプレートとレスポンス JSON 雛形を生成します。
--tags を指定した場合は、指定 tag を持つ operation のみを対象にします。
生成された mock-cases.yaml を編集して、返し分け条件とレスポンス内容を定義します。
oapi2wire build \
--openapi ./openapi.yaml \
--cases ./mock-cases.yaml \
--responses-root ./mock-responses \
--out ./wiremock-out \
--tags petoapi2wire validate \
--openapi ./openapi.yaml \
--cases ./mock-cases.yaml \
--responses-root ./mock-responses \
--tags petoapi2wire init --openapi <path> [flags]
| フラグ | デフォルト | 説明 |
|---|---|---|
--openapi |
(必須) | OpenAPI ファイルのパス |
--out-cases |
mock-cases.yaml |
出力する case YAML のパス |
--responses-root |
mock-responses |
レスポンス雛形の出力ディレクトリ |
--force |
false |
既存ファイルを上書きする |
--strict |
false |
OpenAPI の不整合をエラーとして扱う |
--tags |
なし | 対象にする OpenAPI operation tag(複数指定可) |
oapi2wire build --openapi <path> [flags]
| フラグ | デフォルト | 説明 |
|---|---|---|
--openapi |
(必須) | OpenAPI ファイルのパス |
--cases |
mock-cases.yaml |
case YAML のパス |
--responses-root |
mock-responses |
レスポンス JSON のディレクトリ |
--out |
wiremock-out |
出力ディレクトリ |
--clean |
false |
出力先を削除してから再生成する |
--strict |
false |
不明項目をエラーとして扱う |
--fail-on-missing-operation |
false |
operationId が OpenAPI に存在しない場合エラー |
--fail-on-missing-body-file |
false |
bodyFile が存在しない場合エラー |
--no-auto-fallback |
false |
fallback の自動生成を無効化する |
--tags |
なし | 対象にする OpenAPI operation tag(複数指定可) |
oapi2wire validate --openapi <path> [flags]
| フラグ | デフォルト | 説明 |
|---|---|---|
--openapi |
(必須) | OpenAPI ファイルのパス |
--cases |
mock-cases.yaml |
case YAML のパス |
--responses-root |
mock-responses |
レスポンス JSON のディレクトリ |
--tags |
なし | 対象にする OpenAPI operation tag(複数指定可) |
init / validate / build は OpenAPI operation の tags で対象 operation を絞り込めます。
oapi2wire init --openapi ./openapi.yaml --tags pet
oapi2wire validate --openapi ./openapi.yaml --cases ./mock-cases.yaml --tags pet
oapi2wire build --openapi ./openapi.yaml --cases ./mock-cases.yaml --tags pet--tags未指定の場合は、従来どおり全 operation が対象です--tags petの場合はtags: ["pet"]を持つ operation のみ対象です--tags pet,storeの場合はpetまたはstoreを持つ operation が対象です- tag 比較は完全一致・大文字小文字を区別します
- tag フィルタ指定時、tag を持たない operation は対象外です
buildの自動 fallback 生成も tag 対象 operation のみに行われます
tag フィルタ指定時に case YAML 内へ対象外 operation の case が残っている場合、validate は missing operation エラーとは扱わず、対象外であることを warning として報告します。
Go の公開 API からも同じフィルタを利用できます。
result, err := oapi2wire.Init(oapi2wire.InitOptions{
OpenAPIPath: "./openapi.yaml",
OutCasesPath: "./mock-cases.yaml",
ResponsesRoot: "./mock-responses",
Tags: []string{"pet"},
})version: 1
defaults:
response:
headers:
Content-Type: application/json
cases:
- ...- id: getUser_detail_100
operationId: getUser
priority: 10
request:
pathParams:
id:
equalTo: "100"
query:
mode:
equalTo: "detail"
body:
equalToJson:
role: admin
matchesJsonPath:
- "$.options.mode[?(@ == 'detail')]"
response:
status: 200
headers:
Content-Type: application/json
bodyFile: getUser/getUser_detail_100.json| 種別 | フィールド | 対象 |
|---|---|---|
equalTo |
文字列の完全一致 | pathParams, query |
matches |
正規表現一致 | pathParams, query |
equalToJson |
JSON オブジェクトの一致 | body |
matchesJsonPath |
JSONPath 式による一致 | body |
equalToJson と matchesJsonPath は同時指定可能です。
- id: getUser_fallback
operationId: getUser
fallback: true
priority: 10000
response:
status: 501
bodyFile: common/getUser_fallback.jsonfallback: trueのときrequestは指定できませんoperationIdごとに 1 件まで- 明示 fallback がない場合、
build時に自動生成されます(status: 501)
project/
├─ openapi.yaml
├─ mock-cases.yaml
└─ mock-responses/
├─ getUser/
│ └─ getUser_default.json
└─ createUser/
└─ createUser_default.json
wiremock-out/
├─ mappings/
│ ├─ getUser__getUser_default.json
│ ├─ createUser__createUser_default.json
│ └─ _generated__fallback__getUser.json
└─ __files/
├─ getUser/
│ └─ getUser_default.json
├─ createUser/
│ └─ createUser_default.json
└─ _generated/
└─ fallback/
└─ getUser.json
| 種別 | パターン |
|---|---|
| case id | <operationId>_<caseName> |
| mapping ファイル | <operationId>__<caseId>.json |
| bodyFile | <operationId>/<caseId>.json |
| 自動 fallback mapping | _generated__fallback__<operationId>.json |
| 自動 fallback body | _generated/fallback/<operationId>.json |
openapi: 3.0.3
info:
title: Sample API
version: 1.0.0
paths:
/users/{id}:
get:
tags:
- pet
operationId: getUser
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: query
name: mode
required: false
schema:
type: string
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
id:
type: string
name:
type: string
/users:
post:
tags:
- user
operationId: createUser
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
role:
type: string
responses:
'201':
description: Createdversion: 1
defaults:
response:
headers:
Content-Type: application/json
cases:
- id: getUser_default
operationId: getUser
priority: 100
request:
pathParams:
id:
equalTo: "TODO"
# optional query parameters:
# mode:
# equalTo: "TODO"
response:
status: 200
bodyFile: getUser/getUser_default.json
- id: createUser_default
operationId: createUser
priority: 100
request:
body:
equalToJson:
name: "TODO"
role: "TODO"
response:
status: 201
bodyFile: createUser/createUser_default.json{
"id": "getUser_detail_100",
"name": "getUser_detail_100",
"priority": 10,
"metadata": {
"generator": "oapi2wire",
"operationId": "getUser",
"caseId": "getUser_detail_100"
},
"request": {
"method": "GET",
"urlPathTemplate": "/users/{id}",
"pathParameters": {
"id": { "equalTo": "100" }
},
"queryParameters": {
"mode": { "equalTo": "detail" }
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"bodyFileName": "getUser/getUser_detail_100.json"
}
}- OpenAPI が読めない
- OpenAPI 内の
operationIdが重複している - case の
idが重複している - case の
operationIdが OpenAPI に存在しない(--fail-on-missing-operation時) - 同じ
operationIdに fallback が複数ある - fallback ケースに
requestが指定されている pathParamsのキー名が OpenAPI の path parameter 名と一致しないbodyFileに絶対パス・..を含む禁止パスが指定されているbodyFileが存在しない(--fail-on-missing-body-file時)
- matcher が空で fallback でもないケース
- 同一
operationId+ 同一 request 条件のケースが重複している - priority が重複している
- OpenAPI に
requestBodyがあるが body matcher が指定されていない
# テスト実行
go test ./...
# ビルド
go build -o oapi2wire .LICENSE を参照してください。