狛ログ

2022年10月3日月曜日

node.jsでnockライブラリを使って外部API呼び出しをモック化させる。

オフィス狛 技術部のHammarです。

node.jsでAPIを実装しているプロジェクトにユニットテストを実施することになり、いろいろと自動化させています。
このユニットテストにおいて、外部のAPIを呼び出す処理は、実際に外部APIを呼ばずに、APIモックを作成してテストするということになり、今回nockというライブラリを使って簡単にモックを作成ができたので、ご紹介したいと思います。

実行環境

※ユニットテストではjestを使います
  • Node.js  v12.14.0
  • jest           v27.5.1
  • nock        v13.2.4


以下代表的なGETとPOSTのテストについてサンプルを書いてみます。

GETの場合

テスト対象となるプログラムの例として、以下GETリクエストのプログラムを作成します。
■testGetRequest.js
const request = require('request');

exports.getUserInfo = async () => {
  // リクエスト作成
  const requests = {
    url: 'https://test.com/users',
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    },
    json: true,
  };

  // リクエスト送信
  return new Promise((resolve, reject) => {
    request(requests, async (error, response, body) => {
      if (error) {
        reject(error);
      } else if (response.statusCode !== 200) {
        reject(response);
      } else {
        resolve(body);
      }
    });
  });
};
上記をnockを使ったテストコードを書くと以下のようになります。
■testGetRequest.test.js
const nock = require('nock');

describe('ユーザー情報取得のTest', () => {
  let resData;

  beforeEach(() => {
    // レスポンス
    resData = {
      user_id: '1',
      user_name: 'テスト太郎',
    };
  });

  afterEach(() => {
    nock.cleanAll();
    jest.clearAllMocks();
  });

  it('ユーザー情報取得リクエスト', async () => {
    // APIリクエストのモック
    nock('https://test.com')
      .get('/users')
      .reply(200, resData);

    const repos = await testGetRequest.getUserInfo();

    expect(repos.user_id).toEqual('1');
    expect(repos.user_name).toEqual('テスト太郎');
    expect(nock.isDone()).toBe(true);
  });
上記のnock('https://test.com').get('/users')が、テスト対象プログラム(testGetRequest.js)のgetUserInfo()で呼んでいるAPIリクエストのパスと一致、かつHTTPメソッドも同じにすることによって、resDataに記述したモックするレスポンス内容を返すことができるようになります。
ちなみにnock.isDone()で、リクエストをしたかどうかを判定できます。

続いて、POSTリクエストの例が以下になります。

POSTの場合

■testPostRequest.js
const request = require('request');

exports.entryUserInfo = async (userId, userName) => {
  // リクエストBODY
  const bodyData = {
    user_id: userId,
    user_name: userName,
  };

  // リクエスト作成
  const requests = {
    url: 'https://test.com/users',
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: bodyData,
    json: true,
  };

  // リクエスト送信
  return new Promise((resolve, reject) => {
    request(requests, async (error, response, body) => {
      if (error) {
        reject(error);
      } else if (response.statusCode !== 200) {
        reject(response);
      } else {
        resolve(body);
      }
    });
  });
};
上記のテストコードを書くと以下のようになります。
■testPostRequest.test.js
const nock = require('nock');

describe('ユーザー情報登録のTest', () => {
  let userId;
  let userName;
  let reqBody;
  let resData;
  
  beforeEach(() => {
    userId = '1';
    userName = 'テスト太郎'

    reqBody = {
      user_id: userId,
      user_name: userName,
    };
    // レスポンス
    resData = {
      message: '登録完了しました',
    };
  });

  afterEach(() => {
    nock.cleanAll();
    jest.clearAllMocks();
  });

  it('ユーザー情報登録リクエスト', async () => {
    // APIリクエストのモック
    nock('https://test.com')
      .post('/users', reqBody)
      .reply(200, resData);

    const repos = await testPostRequest.entryUserInfo(userId, userName);

    expect(repos.message).toEqual('登録完了しました');
    expect(nock.isDone()).toBe(true);
  });
});
GETの時と同様に、リクエストのパスとHTTPメソッドを一致させることでモック作成が可能となります。
POSTの場合は、上記.post('/users', reqBody)でリクエストボディの内容を設定できます。
ちなみに、テストを実行した後は、nock.cleanAll()でモックをクリアする必要がありますので、忘れずに。

上記のように、思っていた以上に楽にAPIリクエストのモックを作成することが出来るようになりました。
公式の情報を確認すると、さらに細かくモック設定できそうなので、細かなテストにも対応できそうです!

0 件のコメント:

コメントを投稿