[Node.JS]開発後テスト-ユニットテスト

29735 ワード

開発と導入を完了する前に、テストを行う必要があります.
ノードが作成したサーバをテストするときにjestというパッケージを使用します.
Jestはフェイスブックに作成されたテストパッケージです.

package.jsonに「test」を追加

"scripts": {
    "start": "nodemon server",
    "test": "jest",
packageは、testの入力時にjestを実行するために使用されます.jsonに「test」を追加します.
npm testを入力すると、jestは拡張子にtestが含まれているすべてのファイルを検索してテストします.

test関数


sum.js

function sum(a, b) {
  return a + b;
}
module.exports = sum;
sum.test.js
test('two plus two is four', () => {
  expect(2 + 2).toBe(4);
});
sum.jsをテストするためのコードsum.test.jsです.test関数の最初のパラメータはテストの説明です.
2番目のパラメータはテスト関数です.コードを表示することで、関数を直感的に理解できます.
2+2の基数値は4です.2+2が4ではなく4面テストに合格した場合、テストは失敗します.

上記のコードを実行するとテストに合格します.

tobeのパラメータを5に変更すると、上記のテストに失敗した文が表示されます.
.test(name, fn, timeout)
name:テストの説明
fn:テスト関数

テスト関数にはexpectという関数が表示されます.expectの後ろにはmatcherというtoBeという関数があります.
expect関数は単独ではあまり使用されず、matcherとともにexpect関数の戻り値がmatcherと一致するかどうかを確認するために使用されます.

.expect(value)
value:値.関数を通常のパラメータとして使用して、関数の戻り値を渡します.

.toBe(value)
値の比較に使用します.
value:比較する値

describe関数


相互に関連付けられたテストを組み合わせる場合はdescribeという関数を使用します.
const myBeverage = {
  delicious: true,
  sour: false,
};

describe('my beverage', () => {
  test('is delicious', () => {
    expect(myBeverage.delicious).toBeTruthy();
  });

  test('is not sour', () => {
    expect(myBeverage.sour).toBeFalsy();
  });
});
テストグループの名前はmy飲料です.次にtest関数を関数でバンドルします.
一つ目はMyBeveragedeliciousが本当かどうかをテストしますそしてMyBeveragesugarがfalseであるかどうかをテストします.
.describe(name, fn)
name:テストグループの名前
fn:テスト関数の集合

コンソールウィンドウでmybeadableというテストのセットが合格したかどうかが表示されます.

mocking - mock function


forEach.js
function forEach(items, callback) {
  for (let index = 0; index < items.length; index++) {
    callback(items[index]);
  }
}
上記のforEach関数を持ちます.forEach関数をテストするにはitems関数とcallback関数が必要です.
上記のコードをテストする場合は、実際のcallback関数ではなく、一時的なテスト関数を作成できます.テストに使用する関数やオブジェクトなどを作成することをmockingと呼びます.

forEach.test.js
forEach = require('./forEach');

test('forEach()', () => {
  const mockCallback = jest.fn(x => 42 + x);
  forEach([0, 1], mockCallback);

  // The mock function is called twice
  // same as expect(mockCallback).toBeCalledTimes(2);
  expect(mockCallback.mock.calls.length).toBe(2);

  // The first argument of the first call to the function was 0
  expect(mockCallback.mock.calls[0][0]).toBe(0);

  // The first argument of the second call to the function was 1
  expect(mockCallback.mock.calls[1][0]).toBe(1);

  // The return value of the first call to the function was 42
  expect(mockCallback.mock.results[0].value).toBe(42);
})
mockCallbackという名前の関数を作成し、forEach関数の2番目のパラメータcallbackを追跡します.
関数を真似するために冗談を言うfn()という名前の関数を使用します.jest.fn(x=>42+x)は、関数(x=>x+42)が追跡されることを示す.
まず、mockCalback関数を呼び出す回数をテストします.次に、最初の再呼び出しの最初のパラメータが0であるかどうかをテストします.次に、2回目の呼び出しの最初の再パラメータが1であるかどうかをテストします.次に、最初の呼び出しの戻り値が42であるかどうかをテストします.
上記のテストに合格します.
jest.fn(implementation)
インプリメンテーション:シミュレーションするコンテンツ
mockFn.mock.calls
i回呼び出しにおけるj回パラメータを有する配列
例えば、f(「arg 1」、「arg 2」)を呼び出し、f(「arg 3」、「arg 4」)を呼び出す.
[
  ['arg1', 'arg2'],
  ['arg3', 'arg4'],
];
mockFn.mock.呼び出しにはこの配列があります.
mockFn.mock.results
typeとvalueを要素とする配列.
[
  {
    type: 'return',
    value: 'result1',
  },
  {
    type: 'throw',
    value: {
      /* Error instance */
    },
  },
  {
    type: 'return',
    value: 'result2',
  },
];
例えば、ある関数fが3回呼び出されたときのmockFnである.mock.結果は以下の通りです.
mockFn.mockName(value)
const mockFn = jest.fn().mockName('mockedFunction');
// mockFn();
expect(mockFn).toHaveBeenCalled();
value:mock関数の名前
mock関数でjestを使用します.fn()の名前を付ける関数です.
mockfn.mockReturnThis()
mock関数は自分を返します.
mockFn.mockReturnValue(value)
const mock = jest.fn();
mock.mockReturnValue(42);
mock(); // 42
mock.mockReturnValue(43);
mock(); // 43
mock関数の戻り値を指定する関数.
value:mock関数の戻り値

Mocking - mock modules


Jestは関数だけでなくモジュールもシミュレートできます.
// banana.js
module.exports = () => 'banana';

// __tests__/test.js
jest.mock('../banana');

const banana = require('../banana'); // banana will be explicitly mocked.

banana(); // will return 'undefined' because the function is auto-mocked.
jest.mockするモジュールの名前をmockに渡します.上記の例ではバナナです.シミュレーションjsモジュール.
そしてバナナが必要ならバナナが真似になります
jest.mock('../models/user');
const User = require('../models/user');
const {addFollowing} = require('./user');

describe('addFollowing', ()=>{
  const req = {
    user : {
      id : 1,
    },
    params : {
      id : 2,
    }
  };
  const res = {
    status : jest.fn(()=>res),
    send : jest.fn(),
  };
  const next = jest.fn();

  test('사용자를 찾아 팔로잉을 추가하고 success를 응답해야 함', async()=>{
    User.findOne.mockReturnValue({
      addFollowing(id){
        return Promise.resolve(true);
      }
    });
    await addFollowing(req, res, next);
    expect(res.send).toBeCalledWith('success');
  });

  test('사용자를 못 찾으면 res.status(404).send(no user)를 호출함', async()=>{
    User.findOne.mockReturnValue(null);
    await addFollowing(req, res, next);
    expect(res.status).toBeCalledWith(404);
    expect(res.send).toBeCalledWith('no user');
  });

  test('DB에서 에러가 발생하면 next(error)를 호출함', async()=>{ 
    const error = '테스트용 에러';
    User.findOne.mockReturnValue(Promise.reject(error));
    await addFollowing(req, res, next);
    expect(next).toBeCalledWith(error);
  });
})
コード長.私たちはゆっくり見ます.
冗談を先に言う.mockするモジュールを指定します.userモジュールはsequelizeモデルです.userモジュールにはinitとassociateという方法があります.addFfollowingはuserモジュールに注目を追加する関数です.
addFollowing関数は、req、res、nextオブジェクトが後で必要になるため、req、res、nextオブジェクトを作成します.
最初のステップは、ユーザーを検索し、応答の成功に注目し、テストする部分を追加することです.
sequelzeのクエリーは承諾に基づいているため、承諾を解決または拒否する必要があります.
まずはmockReturnValueで使います.findOneの戻り値は{addFollowing()}オブジェクトとして指定されます.これは、ユーザーを検索し、注目を追加する状況をテストするためです.
次にaddFfollowing関数を呼び出して実際のテストを行います.res.sendがsuccessパラメータとともに呼び出されるかどうかをテストします.
ユーザーが見つからない場合は、次の項目をテストします.
ユーザーが見つからない場合は、関心は追加されませんので、ユーザー.findOneの戻り値をnullとして指定します.次にaddFollowing関数をテストします.この場合、res.statusはパラメータ「404」とともに呼び出され、res.send関数が「no user」とともに呼び出されるかどうかをテストします.
最後にユーザーを検索中にエラーが発生しました.
この時はUserpromise findOneの戻り値.拒否(error)として指定します.次にaddFollowingを呼び出してnextがerrorとともに呼び出されるかどうかをテストします.

整理する


デフォルトではtest(name,fn)関数を使用してテストします.複数の類似したテストをグループ化する場合、describe(name,implementation)関数を使用してグループ化できます.
expect関数やtoBe、toBeCalledWithなどのマッチングを使用して、テストの部分が正常に動作しているかどうかをテストします.
テスト中の関数のパラメータまたは関数の内部で別の関数またはモジュールを使用する場合があります.この場合、テストの範囲に応じて適切なシミュレーションを行うことができる.jestではjestfn(), jest.mock()など多様な移動方法を用いる.
コードをテストするには、私が書いたコードについて十分な理解が必要です.各関数で使用される変数、オブジェクト、関数を明確に理解する必要があります.また、各テストケースの正しい戻り値が何であるか、エラーが発生した場合、コードがどのように処理されるかを知る必要があります.また、適切な戻り値を指定するには、私が使用している関数がpromiseに基づいているかどうかを知る必要があります.
言語に慣れていない場合は、テストコードを書く時間が長くなる可能性があります.適切なテストコードをすばやく作成するには、まず言語を理解する必要があります.