👻
Nuxt3にVItestとMSWを入れてAPIモックでのテストに詰まった点のメモ
はじめに
Nuxt3環境でAPI(RestAPI)のテストを行おうとした際にMock Service Worker(MSW)とVitestで対応していたがその際に詰まった点を記録しておく。
そのため環境設定周りは省略する。
最初に今回行いたいテストについて
piniaでトークンを保有しているストアがあり、内部は下記のようになっている。
今回テストしたい内容は下記である。
APIモックを使用し、fetchToken()
をした際にgetToken()
でトークンが保有されているかをテスト
トークンのpinia構成
store: トークン
methods:
getToken(): トークン取得する
setToken(): トークンを設定する
fetchToken(): トークンをAPIからGETし、setToken()を使い、storeにトークンを設定する
詰まった点
MSWへのリクエストした際にCaused by: TypeError: Cannot read properties of undefined (reading 'status')と出力される
mswのAPIモック構成は以下。
mock
│ handlers.ts(api配下のレスポンスそれぞれをハンドルする)
│ setup.ts (setupSeverの記述)
│
└─api (APIそれぞれのダミーレスポンスを格納する)
dummy.ts
構成としては問題なかったが、原因としては、公式ドキュメントをしっかりと読んでいなかったためのものであった。
原因
MSWでのRESTAPIの記述が変更されていたため。
rest記述からhttp記述からに変更されていた。
rest.get()
→ http.get()
それによってレスポンスも以下に変更。
before
res(
ctx.status(200),
ctx.json([
{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'bar',
}
]),
)
after
HttpResponse.json(
{ status: 200 },
{[
{
id: 1,
name: 'foo',
},
{
id: 2,
name: 'bar',
}
]},
)
store側での$fetchができない点
こちらは以下順序で対応した。
unplugin-auto-import
にてofetch/$fetch
に紐付け
1. 結果としては紐付け自体はできたが、fetch時にタイムアウトとなった。
おそらくofetchがnitroサーバー上でしか機能しないためうまく動かなかった。
nitroサーバーをsetup時に起動させれば良いとは思うが少し手間なので、別方法で調査。
@nuxt/test-utils
から$fetch
をimportし使用
2. 試してみたが、同事象が発生し、うまく解決できなかった。
拡張子を.mts
に変更しても解決しなかった。
ofetch/$fetch
をglobalThis.fetchにスパイ
3. 結果これでMSWのAPIにアクセスできテストできた。
setup時に下記のようスパイした。
globalThis.fetchのイメージ
// 最初にofetchのmockを作成
vi.mock("ofetch", () => ({ $fetch: vi.fn() }));
// 一旦getのみなのでoptionsは処理しない
const nodeFetch = async(url,options) => {
const data = await globalThis.fetch(url);
return data.json()
}
// ofetchの$fetchをglobaltThis.fetchを使用したnode側でのfetch関数へスパイ
vi.spyOn(await import('ofetch'), '$fetch').mockImplementation(nodeFetch)
最後に
@nuxt/test-utils
が使えればもう少し使いやすいかな?とは思う。
今回は$fetch
の対応ですが、次はuseFetch
の対応をどのように入れるかを考えなければならない。。。
やはりフロントのテストが難しい。。
Discussion