JestでTypeScriptのテストを書く(Step2:Matcherを利用する)

## はじめに
表題通り、JestでTypeScriptのテストを書きます。
下記StepでJestの学習を進めていきます

[Step1: Jest(環境構築から実行まで)](https://qiita.com/koji0705/items/258166f4f281efbb2c46)
[Step2: Jest(Matcherを利用する)](https://qiita.com/koji0705/items/2049d581fe7d343d58d3)←今回はここ
[Step3: Jest(API検証)](https://qiita.com/koji0705/items/1f7099600a97f3a9b328)
[Step4: Jest(StubとMockとSpy)](https://qiita.com/koji0705/items/191a48e51b9eebb81db1)

https://qiita.com/koji0705/items/258166f4f281efbb2c46

### toBe値の比較
値をテストする最も簡単な方法は、厳密に等価であることです。

```ts:toBeの比較
test('two plus two is four', () => {
  expect(2 + 2).toBe(4);
});
```

```shell:実行結果
~/develop/react/jest_ts$ yarn test sample.test.ts
yarn run v1.22.19
$ jest sample.test.ts
ts-jest[config] (WARN) message TS151001: If you have issues related to imports, you should consider setting `esModuleInterop` to `true` in your TypeScript configuration file (usually `tsconfig.json`). See https://blogs.msdn.microsoft.com/typescript/2018/01/31/announcing-typescript-2-7/#easier-ecmascript-module-interoperability for more information.
 PASS  src/__tests__/sample.test.ts
  ✓ two plus two is four (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.61 s, estimated 1 s
Ran all test suites matching /sample.test.ts/i.
✨  Done in 0.98s.
```

:::note info
実行時の補足です。
yarn test sample.test.tsのように、ファイル名を指定するとファイル単位での実行ができます。
:::


```ts:オブジェクト比較
const can = {
  name: 'pamplemousse',
  ounces: 12,
};

describe('the can', () => {
  test('has 12 ounces', () => {
    expect(can.ounces).toBe(12);
  });

  test('has a sophisticated name', () => {
    expect(can.name).toBe('pamplemousse');
  });

  test('object compare', () => {
    const actual = {
      name: 'pamplemousse',
      ounces: 12,
    };
    expect(can).toEqual(actual);
  });
});

```

:::note info
オブジェクトの比較では、toBeでなくtoEqualを利用します。
参照比較になるため、異なるポインタの場合、不一致となりエラーになります。
:::


<details><summary>Appendix(nullの比較)</summary>
nullの比較はちょっと想像しづらい部分があるので、記載しておきます。

```ts:null比較
test('null', () => {
  const n = null;
  expect(n).toBeNull(); // nullであるかチェック
  expect(n).toBeDefined();　// 定義済みであるかチェック
  expect(n).not.toBeUndefined(); // undefindであるかチェック
  expect(n).not.toBeTruthy(); // trueであるかチェック
  expect(n).toBeFalsy();　// falseであるかチェック
});
```
:::note info
上記は全てパスします。
.not.toBeTruthy、toBeFalsyが通ります。TypeScriptではnullはfalse判定。
詳細は下記URLを参考
https://developer.mozilla.org/ja/docs/Glossary/Falsy
:::

</details>


## 数値の比較
```ts:実行値>期待値
test('greater than', () => {
  expect(10).toBeGreaterThan(8);
  expect(10).not.toBeGreaterThan(10); // 実行結果=期待値の場合
});
```

```ts:実行値=>期待値
test('greater than or equal', () => {
  expect(10).toBeGreaterThanOrEqual(10);
});
```


```ts:実行値<期待値
test('less than', () => {
  expect(7).toBeLessThan(8);
  expect(7).not.toBeLessThan(7); // 実行値=期待値の場合は失敗のため、notを付与する
});
```

```ts:実行値<=期待値
test('less than or equal', () => {
  expect(7).toBeLessThanOrEqual(7);
});
```

```ts:小数点比較
test('close to', () => {
  expect(0.2 + 0.1).toBeCloseTo(0.3);
});

```

### 文字列の比較
```ts:文字列の完全一致
test('team is team', () => {
  expect('team').toBe('team');
});
```

```ts:文字列内に任意の文字が含まれるか
test('the team name includes "team"', () => {
  expect('team').toContain('team'); // teamの中にteamが含まれているか
  expect('team2').toContain('team'); // team2の中にteamが含まれているか
  expect('team2').not.toContain('team1'); // team2の中にteam1が含まれていないか
});
```

```ts:文字列の正規表現比較
test('email is in correct format', () => {
  const email = 'user@example.com';
  const dummyEmail = 'dummy.com';
  expect(email).toMatch(/^\S+@\S+\.\S+$/);
  expect(dummyEmail).not.toMatch(/^\S+@\S+\.\S+$/);
});
```

## エラー時の検証
```ts:エラーが発生することの検証
function compileAndroidCode() {
  throw new Error('you are using the wrong JDK');
}

test('compileAndroidCode throws an error', () => {
  expect(compileAndroidCode).toThrow();
  expect(compileAndroidCode).toThrow(Error);
});

```

```ts:エラーメッセージの検証
function compileAndroidCode() {
  throw new Error('you are using the wrong JDK');
}

test('compileAndroidCode throws an error with specific message', () => {
  expect(compileAndroidCode).toThrow('you are using the wrong JDK');
  expect(compileAndroidCode).toThrow(/JDK/);
});
```

## 最後に
今回はJestのMatcherに関して学びました。
次回は非同期関数の検証方法について記載しようと思います。