🐙

tanstack query のtestでAPIをMockする

2023/12/25に公開

概要

tanstack queryでAPIをモックするという話です。

一般的にAPIのモックはmswのようなモックサーバを使う方法とjestのモックを使う2種類のやり方があるかと思いますが、ここで紹介するのはjestの方です。

jestのmock

APIは適当にポケモンのピカチュウの情報を取得できる形とします。ここでピカチュウの取得APIは以下のように定義できます。

fetcher.ts
export const getPokemon = async (pokemonName: string) => {
  return await fetch(`v2/pokemon/${pokemonName}`)
}

という形でポケモンを取得します。なお、ポケモンAPIは以下を参照しています。

https://pokeapi.co/

続いて、コンポーネントの方を定義します。Container/presentationみたいに定義しています。

PokemonContainer.tsx
type PokemonContainerProps = { params: { pokemonName: string } }

export const PokemonContainer = ({ params }: PokemonContainerProps)=>{
  const { data } = useQuery(['pokemon', params.pokemonName], async () => await getPokemon(params.pokemonName), { enabled: params.pokemonName !== undefined })
  return (
    <>
      <Pokemon data={data} />
    </>
  )
}
pokemon.tsx
export const Pokemon = ({ data }: PokemonProps) => {
 
  return (
    <div>
      { data && <div>{data.id}</div> }
      )
     }
    )

テストではgetPokemonをmockすることでuseQueryは動かすことができます。

__mock__/jest.ts
import * as Fetcher from '../fetcher'
import { mockPokemonPickachu } from '@/domain/pokemon/__mock__/mockPokemon'

//fetcherの中身全体をmockとして定義しておく
jest.mock('../fetcher')

//スパイモックとして返す
export function mockGetPokemon() {
  return jest.spyOn(Fetcher, 'getPokemon').mockResolvedValue(mockPokemonPickachu)
}

コンポーネントのテストを記載します。

pokemonContainer.test.tsx
const setup = async ()=> {
  render(<TestQueryClientProvider>
    <PokemonContainer params={{ pokemonName: 'pickachu' }}/>
  </TestQueryClientProvider>)
}
beforeEach(() =>{
  jest.resetAllMocks()
})

describe('レンダリングテスト', () => {
  test('APIをhook経由で呼び出せるか', async () =>{
    //given
    const getPokemon = mockGetPokemon()
    setup()

    //then
    expect(await screen.findByText('25')).toBeInTheDocument()
    //呼び出されたかチェック
    expect(getPokemon).toHaveBeenCalled()
    //引数が期待値通りであるかチェック
    expect(getPokemon).toHaveBeenCalledWith('pickachu')
  })
})

Discussion