Jestを使った関数のテストについて
今回は、Jestを使用して関数をテストするサンプルプログラムについて、わかりやすく解説していきます。
下記はテスト元のサンプルプログラムになります
/**
* 指定された郵便番号から住所を取得するためにAPIを呼び出します。
* @param {string} zipcode - 検索する郵便番号(ハイフンなしの7桁)。
* @returns {Promise} - APIからのレスポンスを含むPromiseオブジェクト。
* @throws {Error} - 引数が空の文字列であるか、7桁の数字でない場合にエラーをスローします。
*/
function getZipCloud(zipcode) {
if (!zipcode) {
return Promise.reject(new Error("郵便番号を入力してください。"));
} else if (!/^\d{7}$/.test(zipcode)) {
return Promise.reject(
new Error("郵便番号は7桁の数字である必要があります。")
);
} else {
/**
* 指定された郵便番号から住所を取得するためにAPIを呼び出すURL。
* @type {string}
*/
const url = `http://zipcloud.ibsnet.co.jp/api/search?zipcode=${zipcode}`;
/**
* fetch関数を使用してAPIを呼び出します。
* @returns {Promise} - APIからのレスポンスを含むPromiseオブジェクト。
* @throws {Error} - HTTPレスポンスがOKでない場合、またはJSONレスポンスの解析中にエラーが発生した場合にエラーをスローします。
*/
return fetch(url)
.then((res) => {
if (!res.ok) {
throw new Error(`HTTPエラー:${res.status}`);
}
return res.json();
})
.then((data) => {
console.log(data);
return data;
})
.catch((err) => {
throw err;
});
}
}
/**
* getZipCloud関数を呼び出して、結果をコンソールにログ出力します。
*/
getZipCloud("1000001")
.then((result) => {
console.log(result);
console.log(result.results[0].address1);
})
.catch((err) => {
console.error(err.message);
});
/**
* getZipCloud関数をエクスポートします。
*/
module.exports = {
getZipCloud,
};
Jestを使ったgetZipCloud
関数のテストについて
前提
以下のコードは、getZipCloud
関数をテストするためのJestのサンプルプログラムです。この関数は、郵便番号を引数として受け取り、何らかの処理を行うものとします。
const { getZipCloud } = require("./testes");
テストの概要
-
HTTPモジュールのモック化
Jestを使用してHTTPモジュールをモック化します。 -
jest.mock("http");
-
getZipCloud
関数のテストケースの記述describe
関数を使用して、getZipCloud
関数のテストケースをグループ化します。describe("getZipCloud", () => {
-
郵便番号が提供されなかった場合のテスト
関数に何も引数を渡さなかった場合、エラーメッセージ「郵便番号を入力してください。」が返されることを確認します。
it("should reject with an error if no zipcode is provided", async () => { await expect(getZipCloud()).rejects.toThrow("郵便番号を入力してください。"); });
-
無効な郵便番号が提供された場合のテスト
無効な郵便番号(例: "123456")を関数に渡した場合、エラーメッセージ「郵便番号は7桁の数字である必要があります。」が返されることを確認します。
it("should reject with an error if an invalid zipcode is provided", async () => { await expect(getZipCloud("123456")).rejects.toThrow("郵便番号は7桁の数字である必要があります。"); });
-
有効な郵便番号が提供された場合のテスト
有効な郵便番号(例: "1000000")を関数に渡した場合、期待されるデータ(この場合は"ああああ")が返されることを確認します。
it("should resolve with the data from the API if a valid zipcode is provided", async () => { const mockData = { results: [{ address1: "ああああ" }] }; const mockResponse = { ok: true, json: jest.fn().mockResolvedValue(mockData), }; global.fetch = jest.fn().mockResolvedValue(mockResponse); const result = await getZipCloud("1000000"); expect(result).toEqual("ああああ"); });
-
APIがエラーを返した場合のテスト
APIからエラーが返された場合(例: ステータスコード500)、関数がそのエラーを正しく処理することを確認します。
it("should reject with an error if the API returns an error", async () => { const mockError = new Error("API error"); const mockResponse = { ok: false, status: 500, }; global.fetch = jest.fn().mockResolvedValue(mockResponse); await expect(getZipCloud("1234567")).rejects.toThrow(`HTTP error: ${mockResponse.status}`); });
-
以上が、Jestを使用してgetZipCloud
関数をテストするサンプルプログラムのマークダウン形式での説明でした。このサンプルを参考に、自身のコードのテストも行ってみてくださいね!
補足モックに関する部分を詳しく解説
モック (Mocking) とは
モックはテストの際に実際のオブジェクトや関数の代わりに使用されるものです。モックを使用する主な理由は以下の通りです:
-
外部の依存関係を排除する:例えば、外部APIやデータベースへのアクセスを伴う関数をテストする場合、そのAPIやデータベースが常に利用可能であるとは限りません。モックを使用することで、これらの外部依存関係を模倣(モック化)して、テストを安定的に行うことができます。
-
テストの速度を向上させる:外部サービスへの実際のリクエストは時間がかかることがあります。モックを使用することで、リアルタイムの待機時間を排除し、テストの速度を向上させることができます。
-
特定のシナリオをシミュレートする:例えば、エラーシナリオや特定のレスポンスを返すシナリオなど、実際の環境では再現が難しいケースをモックを使用してシミュレートすることができます。
サンプルプログラム内のモックについて
// Mocks the http module
jest.mock("http");
上記のコードでは、http
モジュールがモック化されています。これにより、http
モジュールの実際の動作を行わず、Jestが提供するモック関数やオブジェクトを使用してテストを行うことができます。
また、以下の部分ではfetch
関数(外部APIへのリクエストを行う関数)がモック化されています。
const mockResponse = {
ok: true,
json: jest.fn().mockResolvedValue(mockData),
};
global.fetch = jest.fn().mockResolvedValue(mockResponse);
このモックにより、getZipCloud
関数がfetch
関数を呼び出す際、実際のAPIリクエストを行う代わりにモックデータを返すようになります。これにより、APIの実際のレスポンスに依存せずに、関数の動作をテストすることができます。
モックは、テストの際に非常に有用なツールとなります。特に外部サービスやモジュールに依存する関数のテストを行う際には、モックを使用してテストの安定性や再現性を確保することが推奨されます。