web-dev-qa-db-ja.com

TypescriptとJest:モック関数の型エラーを回避する

Jestで外部モジュールをモックする場合、jest.mock()メソッドを使用してモジュールの関数を自動モックできます。

その後、必要に応じて、モックされたモジュール上のモックされた関数を操作および調査できます。

たとえば、axiosモジュールをモックするための次の不自然な例を考えてみましょう。

_import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';

jest.mock('axios');

it('Calls the GET method as expected', async () => {
  const expectedResult: string = 'result';

  axios.get.mockReturnValueOnce({ data: expectedResult });
  const result = await myModuleThatCallsAxios.makeGetRequest();

  expect(axios.get).toHaveBeenCalled();
  expect(result).toBe(expectedResult);
});
_

上記はJestで正常に実行されますが、TypeScriptエラーがスローされます。

プロパティ 'mockReturnValueOnce'はタイプ '(url:string、config ?: AxiosRequestConfig | undefined)=> AxiosPromise'に存在しません。

_axios.get_のtypedefには、当然mockReturnValueOnceプロパティが含まれていません。 Object(axios.get)としてラップすることにより、TypeScriptに_axios.get_をObjectリテラルとして処理させることができますが、

型の安全性を維持しながら関数をモックする慣用的な方法は何ですか?

14
duncanhall

このコード行を追加const mockedAxios = axios as jest.Mocked<typeof axios>。そして、mockedAxiosを使用してmockReturnValueOnceを呼び出します。コードでは、次のように実行する必要があります。

import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';

jest.mock('axios');
const mockedAxios = axios as jest.Mocked<typeof axios>;

it('Calls the GET method as expected', async () => {
  const expectedResult: string = 'result';

  mockedAxios.get.mockReturnValueOnce({ data: expectedResult });
  const result = await myModuleThatCallsAxios.makeGetRequest();

  expect(mockedAxios.get).toHaveBeenCalled();
  expect(result).toBe(expectedResult);
});
22
hutabalian

型の安全性を維持しながら関数を慣用的にモックするには、 spyOnmockReturnValueOnce を組み合わせて使用​​します。

import myModuleThatCallsAxios from '../myModule';
import axios from 'axios';

it('Calls the GET method as expected', async () => {
  const expectedResult: string = 'result';

  // set up mock for axios.get
  const mock = jest.spyOn(axios, 'get');
  mock.mockReturnValueOnce({ data: expectedResult });

  const result = await myModuleThatCallsAxios.makeGetRequest();

  expect(mock).toHaveBeenCalled();
  expect(result).toBe(expectedResult);

  // restore axios.get
  mock.mockRestore();
});
12

インポートに新しい機能を提供してdeclare module "axios" { ... }などの元のモジュールを拡張する通常のアプローチ。モックはあるテストでは利用でき、別のテストでは利用できない場合がありますが、ここでは最適な選択ではありません。

この場合、タイプセーフなアプローチは、必要に応じてタイプをアサートすることです。

  (axios.get as jest.Mock).mockReturnValueOnce({ data: expectedResult });
  ...
  expect(axios.get as jest.Mock).toHaveBeenCalled();
6
Estus Flask