Quantcast
Channel: かずきのBlog@hatena
Viewing all articles
Browse latest Browse all 1387

TypeScript で Jest 使ってみた

$
0
0

TypeScript(というか JavaScript) のユニットテストって何がいいのかなぁというのがわからなかったので、とりあえず自分の観測範囲でよくみる感じの Jest 試してみました。

とりあえずシンプルに以下のコマンドをうってコンソールで始めてみようと思います。

npm init -y
tsc --init
npm i -D jest
npm i -D @types/jest
npm i -D @types/node

tsconfig.json"outDir": "./dist",を設定してビルド結果が dist フォルダーに出るようにします。そして package.jsonscriptstestjestを設定して、jestの設定に rootDirdistにしておきます。package.jsonは以下のような感じになりました。

{"name": "jestlab",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {"test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {"@types/jest": "^24.0.15",
    "@types/node": "^12.6.1",
    "jest": "^24.8.0"
  },
  "jest": {"rootDir": "./dist"
  }}

calc.tsというファイルを作って以下のようにしてみました。

exportdefaultclass Calc {public add(x: number, y: number): number{return x + y;}}

__tests__/Calc.tsを作ってテストを書いてみる。describe関数でテストをグルーピングして it(test関数でも同じみたい)とか beforeEach, afterEachあたりでテスト本番とかテスト前処理や後処理とか書くのかな?

とりあえずこんな感じにテスト書いて

import Calc from'../calc';

describe('sum test',()=>{var c =new Calc();
    beforeEach(()=>{
        c =new Calc();});
    it('1 + 1 = 2',()=>{
        expect(c.add(1,1)).toBe(2);});
    it('2 + 2 = 4',()=>{
        expect(c.add(2,2)).toBe(4);});});

npm test叩いてみたら以下のような結果になりました。

$ npm test

> jestlab@1.0.0 test /home/okazuki/labs/jestlab
> jest

 PASS  dist/__tests__/calc.js
  sum test
    ✓ 1 + 1 = 2 (7ms)
    ✓ 2 + 2 = 4 (1ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.786s
Ran all test suites.

モックしたい

モック機能もあるみたいなのでついでに。

repo.tsを作って…

exportdefaultclass Repo {async get(): Promise<string>{awaitnew Promise(r => setInterval(r,10000));return"Hello";}}

これをモックしたいと思います。本番だと REST API とか呼んだりする感じ。今回も 10 秒待つのでテストのたびに呼び出されたらたまったもんじゃない感じです。

import Repo from'../repo'import RepoClient from'../repoclient';

jest.mock('../repo');

describe('mock sample',()=>{
    it('generateMessage',async()=>{var getMock = jest.fn(()=> Promise.resolve('Jest hello'));(<jest.Mock>Repo).mockImplementation(()=>{return{
                get: getMock,};});var c =new RepoClient();
        expect(await c.generateMessage('world')).toBe('Jest hello world');
        expect(getMock).toBeCalled();});});

とりあえずモックしたいモジュールを importして jest.mockでモックに差し替えるように設定する。 その後 jest.Mockにキャストして mockImplementationで new された時のダミー実装を返す感じ。単純な関数のモックは jest.fnでやるみたい。jest.fnに対しては toBeCalledみたいな専用のアサート関数があるようです。

なるほどね。import をモックを差し込むポイントとして使う機能があるのなら DI コンテナみたいな仕組みなくてもテスト出来ますね。

モック実装もタイプセーフな雰囲気にしたかったらインターフェース??repo.tsを、とりあえずこんな感じにして

exportinterface Repo {
    get(): Promise<string>;}exportclass RepoImpl implements Repo {async get(): Promise<string>{awaitnew Promise(r => setInterval(r,10000));return"Hello";}}

repoclient.tsRepoImplを使って

import{RepoImpl}from'./repo';exportdefaultclass RepoClient {private readonly repo =new RepoImpl();publicasync generateMessage(x: string){var r =awaitthis.repo.get();return`${r} ${x}`;}}

テストはインターフェースのモックを返すみたいな?

import{RepoImpl, Repo}from'../repo'import RepoClient from'../repoclient';

jest.mock('../repo');

describe('mock sample',()=>{
    it('generateMessage',async()=>{var getMock = jest.fn(()=> Promise.resolve('Jest hello'));(<jest.Mock>RepoImpl).mockImplementation(()=>{return{
                get: getMock,}as Repo;});var c =new RepoClient();
        expect(await c.generateMessage('world')).toBe('Jest hello world');
        expect(getMock).toBeCalled();});});

こうしておくとモックの実装部分で型の間違いが検出出来て便利かも?試しに間違えてみた。

f:id:okazuki:20190709093516p:plain

まとめ

とりあえず動いたけど、世間とあってるのだろうか。


Viewing all articles
Browse latest Browse all 1387

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>