こちらの記事は旧バージョンのものになります
動作確認はしていませんが、現在は修正されたようです
https://github.com/hotmeteor/spectator/blob/0a765f6a93204ab334aa9c221bada0e5869b52f8/src/Middleware.php#L39
みなさんはSwagger Editor等で作成したAPI仕様書と実装の乖離をどのようにテストしていますか?
多くの記事で目にするのは、openapi-psr7-validatorというライブラリです。
こちらはPSR-7に準拠したバリデータを使用するため、リクエストとレスポンスもPSR-7仕様に変換するという、少し面倒な工程が必要となります。
もう少し手軽にテストができるライブラリがないか探していたところ、こちらのSpectatorというライブラリを見つけました。
こちらもリクエストとレスポンスの型をテストできるらしく、試しに使ってみたのですが・・・という記事になります。
環境
PHP 8.0.8
Laravel Framework 8.58.0
Spectator v1.7.1
仕様書の保存場所に注意
今回OpenAPI Specのyamlをapp/OpenApiの中に保存しました。
その場合のSPEC_PATHは以下になります。
SPEC_PATH=app/OpenApi
ErrorException: Undefined variable $response in Middleware.php
こいつが原因で、結局使用をやめました。
テストを作成し実行してみたところ、「200を期待しているのに500エラーが発生してるよ!」というエラーが発生していました。
※通常のFeatureテストを実行すると200が返ってくるので、実装に問題はありません。
Spectatorには
$this->withoutExceptionHandling();
というメソッドがあり、Laravelの検証ハンドラーを無効化しSpectatorのエラーを確認することができます。
こちらを追加し再度テストを実行したところ、ErrorException: Undefined variable $response in Middleware.phpというエラーがライブラリ内部で発生していました。
issueやライブラリの内部を確認したところ、以下の部分でエラーが出ているようでした。
public function handle(Request $request, Closure $next)
{
if (! $this->spectator->getSpec()) {
return $next($request);
}
try {
$response = $this->validate($request, $next);
} catch (InvalidPathException|MalformedSpecException|MissingSpecException|TypeErrorException|UnresolvableReferenceException $exception) {
// ここのせい ここに入ると$responseが未定義のまま返される
$this->spectator->captureRequestValidation($exception);
} catch (\Throwable $exception) {
if ($this->exceptionHandler->shouldReport($exception)) {
return $this->formatResponse($exception, 500);
}
throw $exception;
}
return $response;
}
try catch文の一つ目のcatchが走ると、$responseが未定義のままになってしまってreturnできずエラーが発生するようで、プルリクも作成されていますが2023年1月12日現在マージはされていないようです。
この部分で様々な例外を処理しているのですが、現在の実装だと全て未定義の変数を返す形となり、500エラーとして処理されてしまいます。
よって、テストコードに誤りがあるのか?、ファイルパスの指定に問題があるのか?、仕様書のyamlに誤りがあるのか? といった情報がわからないため、とても使いにくいと感じました。
結論
openapi-psr7-validatorの方がもう少しわかりやすくエラーを吐いてくれるので、おとなしくこちらを使います。
参考