jest-mock-axios では「待機状態のリクエストに対してモックデータを渡す」ようになっている。
この方式の良いところは「リクエスト別にモックデータと検証処理を順次記述(実行)しやすい」ことにある(と勝手に思っている)。
同じように待機状態の fetch
へモックデータを渡す API を作成し、その API から「fetch
が実行されたときの各メソッドの実行履歴」を返すようにした。
これにより「fetch
別にメソッド(モック)の実行履歴が隔離」され、「メソッドの実行順」や「使われた(使われなかった)メソッド」なども把握しやすくなる。
asyncData
へモック($content
)を挿入するfetch()
へ mockResponse()
API でモックデータを渡すasyncData
のテストnuxt-content の fetch 処理は asyncData
の中で使うことが多い(ように感じる)のだが、asyncData
の定番なテスト方法が不明。
今回は「NuxtアプリケーションをJestでテストする - アクトインディ開発者ブログ」を参考に単体でメソッドを実行する方法で対応。ただし、データを使ってレンダリングしたい場合は setData
ではなくインスタンスを 2 つ作成することを前提とした。
Nuxt のライフサイクル的には正しくなさそうだが「this を使わず引数と戻り値でやりとりする」ようなので Local Vue の設定などをあわせておけばさほど問題にはならないと予想。
以下のようなコードをテストする場合。
// pages/index.vue
export default Vue.extend({
async asyncData({ $content, params }) {
const article = await $content('pages/home').fetch()
const images = await $content('gallery').sortBy('position').fetch()
return { article, images }
},
// snip...
})
テストコード側から $content
を引数として asyncData
を実行する。
// test/pages/index.ts
const content = mockContent()
const $content = content.$content
const wrapperAsyncData = shallowMount(indexPage, {
// snip...
})
if (wrapperAsyncData.vm.$options.asyncData) {
const data = wrapperAsyncData.vm.$options.asyncData({
$content,
params: {},
} as any)
snip...
}
asyncData
側では最初のfetch
で待機状態となるので、$content
を検証しmockResponse
でモックデータを渡す 。
// pages/index.vue
const article = await $content('pages/home').fetch()
// test/pages/index.ts
expect($content).toHaveBeenLastCalledWith('pages/home')
await content.mockResponse(mockDataArticle)
続いて 2 番目のfetch
で待機状態となるので、再度 $content
を検証しmockResponse
でモックデータを渡す 。このとき、チェーンリストimagesChain
を受け取っておく。
// pages/index.vue
const images = await $content('gallery').sortBy('position').fetch()
// test/pages/index.ts
expect($content).toHaveBeenLastCalledWith('gallery')
const imagesChain = await content.mockResponse(mockDataImages)
2 番目の fetch
では sortBy
の実行も確認したいので、チェーンリストで確認する。
// test/pages/index.ts
expect(imagesChain.at(0).getMockName()).toEqual('sortBy')
expect(imagesChain.at(0)).toHaveBeenCalledWith('position')
最後にasyncData
からの戻り値を検証する。
// pages/index.vue
return { article, images }
// test/pages/index.ts
expect(await data).toEqual({
article: mockDataArticle,
images: mockDataImages,
})
個人的には jest-mock-nuxt-content を作成することでテストの記述がすっきりしたと感じている。
しかしながら、実際に作成中のプロジェクト内でテストを記述してみると「モックデータを渡した(待機を解除させた)後にチェーンを検証する」ことには違和感があった。
今後はこの辺の違和感を解消できればと考えている。