ホームページ >ウェブフロントエンド >jsチュートリアル >Jest と typescript を使ったモック - チートシート

Jest と typescript を使ったモック - チートシート

Barbara Streisand
Barbara Streisandオリジナル
2024-12-22 22:31:11554ブラウズ

Mocking with Jest and typescript - a cheatsheet

Jest は JavaScript/typescript でインポートをモックするのに優れていますが、実装の詳細を覚えるのは非常に難しいと思います。

関数とオブジェクトはさまざまな方法でモックする必要があり、デフォルトのエクスポートは名前付きエクスポートとは微妙に異なる方法でモックされ、Jest は typescript では特にうまく機能しません。これらすべてを組み合わせると、モック シナリオに適したアプローチを見つけ出すこと、さらには検索することさえ困難になる可能性があります。

このガイドは、インポートがどのようなものであっても、「インポートを模擬するにはどうすればよいですか?」 という質問に答えるために作成しました。デフォルトまたは名前付き、関数またはオブジェクト。

私の環境

私は次のバージョンのソフトウェアを使用してこれらのアプローチをすべてテストしました:

  • ノード v22.11.0
  • jest v29.7.0
  • ts-jest v29.2.5
  • @types/jest v29.5.14

デフォルトの最小限の jest.config.js ファイル:

export default {
  testEnvironment: 'node',
  transform: {
    '^.+.tsx?$': ['ts-jest', {}],
  },
  testMatch: ['**/*.test.ts'],
};

インポートのモック化

広く一般的なインポートは、模擬したいと思うかもしれない 2 つのカテゴリに分類されます。

  • 機能
  • オブジェクト

機能から始めて、両方に順番に取り組みます。

関数のインポート

モジュールからエクスポートされた関数には名前を付けるか、デフォルトを付けることができます。両方を見ていきます。最初:

モジュールからの名前付きエクスポート関数のモック化

これは、モジュールからエクスポートされた名前付き関数をモックするために使用する必要があります。

// ./path/to/module.ts

export function doSomething(...) {
  ...
}

次のように嘲笑することができます:

import { doSomething } from './path/to/module';

// note: This should be the path to the module from the test file,
// NOT from the module that contains the doSomething function itself.
jest.mock('./path/to/module', () => ({
  doSomething: jest.fn(),
}));

...

it('should do something', () => {
  // We need to assert that the function is a jest.Mock
  // so that typescript will allow us to call mock methods.
  (doSomething as jest.Mock).mockReturnValue(mockValue);

  // run your test here

  expect(doSomething).toHaveBeenCalledTimes(1); // etc.
});

モジュールから返されたデフォルト関数をモックする

これは、モジュールからのデフォルトのエクスポートである関数をモックするために使用する必要があります。

// ./path/to/module.ts

export default function doSomething(...) {
  ...
}

名前付きエクスポートと同様にモックされます:

import doSomething from './path/to/module'

jest.mock('./path/to/module', () => ({
  __esModule: true,
  default: jest.fn()
}))

...

it('should do something', () => {
  (doSomething as jest.Mock).mockResolvedValue(mockData);

  // Run your test here

  expect(doSomething).toHaveBeenCalledTimes(5);
});

オブジェクトのインポート

エクスポートされたオブジェクト (クラス、json オブジェクト、その他) をモックする場合、考慮すべきバリエーションがいくつかあります。

  • それは名前付きエクスポートですか?
  • モックしたいメソッドはありますか?

メソッドを使用せずにデフォルトのオブジェクトをモックする

メソッドではなくプロパティ (構成ファイルなど) をモックする必要があるだけの場合は、次の方法で実行します:

import config from '../config';

jest.mock('../config', () => ({
  __esModule: true,
  default: {
    apiKey: '123MockKey',
    ...
  },
}));

...

it('Should do something', () => {
  ...
});

モック化されたプロパティをテストごとに変える必要がある場合:

import config from '../config';

const mockConfig = {
  apiKey: '123MockKey',
  ...
};

jest.mock('../config', () => ({
  __esModule: true,
  default: mockConfig,
}));

...

beforeEach(() => {
  // restore defaults before each test
  mockConfig.apiKey = '123MockKey';
  ...
});

it('Should do something', () => {
  mockConfig.apiKey = 'new value';

  // rest of the test
});

// more tests

メソッドを使用しない名前付きエクスポート オブジェクトのモック化

デフォルトのエクスポート オブジェクトのモックと非常によく似ています:

import { config } from '../config';

const mockConfig = {
  apiKey: '123MockKey',
  ...
};

jest.mock('../config', () => ({
  config: mockConfig,
}));

// the rest is exactly the same as when mocking a default export object.

メソッドを使用してオブジェクトをモックする

メソッドを含むオブジェクトがモジュールからエクスポートされ (名前付きまたはデフォルト)、それらのメソッドの出力をモックする必要がある場合、アプローチは少し異なります。

指定されたクラス:

// ./path/to/module.ts

class ComplicatedThing {
  // properties, fields, constructor etc. go here

  getData() {
    ...
  }

  ...
}

// note: I don't necessarily recommend exporting an instance
// of a class like this - purely illustrative for testing purposes.
// https://medium.com/@lazlojuly/are-node-js-modules-singletons-764ae97519af
export const complicatedThing = new ComplicatedThing(...);

そしてエクスポートされたオブジェクトをモックするには:

export default {
  testEnvironment: 'node',
  transform: {
    '^.+.tsx?$': ['ts-jest', {}],
  },
  testMatch: ['**/*.test.ts'],
};

デフォルトのエクスポート オブジェクトのモックは、モックを定義する場合を除いてまったく同じです。

// ./path/to/module.ts

export function doSomething(...) {
  ...
}

ボーナス: パラメータとしてテスト関数/クラスに直接渡されるオブジェクトのモック メソッド

これは、テストしているモジュールに直接インポートされず、代わりにクラス/関数にパラメーターとして渡されるオブジェクトをモックするためのものです。

注: クラスをモックしている場合は、代わりにインターフェースを作成し、そのモック実装を作成して関数/クラスに渡すことをお勧めします。これにより、以下のような洗練されていない型アサーションの悪ふざけを行う必要がなくなります。

import { doSomething } from './path/to/module';

// note: This should be the path to the module from the test file,
// NOT from the module that contains the doSomething function itself.
jest.mock('./path/to/module', () => ({
  doSomething: jest.fn(),
}));

...

it('should do something', () => {
  // We need to assert that the function is a jest.Mock
  // so that typescript will allow us to call mock methods.
  (doSomething as jest.Mock).mockReturnValue(mockValue);

  // run your test here

  expect(doSomething).toHaveBeenCalledTimes(1); // etc.
});
// ./path/to/module.ts

export default function doSomething(...) {
  ...
}
import doSomething from './path/to/module'

jest.mock('./path/to/module', () => ({
  __esModule: true,
  default: jest.fn()
}))

...

it('should do something', () => {
  (doSomething as jest.Mock).mockResolvedValue(mockData);

  // Run your test here

  expect(doSomething).toHaveBeenCalledTimes(5);
});

結論

これがあなたにとって、そして次にタイプスクリプトでインポートをモックする方法の詳細を思い出すのに苦労する将来の私にとって役立つことを願っています。

これが単純なモックのニーズをすべてカバーし、より複雑なインポートをモックする際の出発点となることを願っています。

読んでいただきありがとうございます。

以上がJest と typescript を使ったモック - チートシートの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。