ドメインのファクトリメソッドを呼び出しているメソッドのテストをするときに、いい感じにmockする方法を学んだのでメモしておきます。
ドメインのstaticメソッドをmockする方法
Interface & Adapter層のGatewayでエンティティをドメインに変換する際に、ドメインの
Driverからデータを取得して、ドメインに変換するメソッドをテストする場合はこんな感じになります。
・NewsGateway.ts
1 2 3 4 | async getNews(): Promise<News> { const newsEntity = await this.newsDriver.getNews(); return this.convertNews(newsEntity) } |
・NewsGateway.test.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ... describe('getNews', () => { it('ニュース一覧を取得することができる', async () => { const newsEntity = mock<NewsEntity[]>() const news = mock<News>() const getNewsMock = jest.fn() when(getNewsMock).calledWith().defaultReturnValue(newsEntity) newsDriver.getNews = getNewsMock const convertNewsMock = jest.fn() when(convertNewsMock).calledWith(newsEntity).defaultReturnValue(news) newsGateway['convertNews'] = convertNewsMock const actual = await newsGateway.getNews() expect(actual).toEqual(news) expect(newsDriver.getNews).nthCalledWith(1) expect(newsGateway['convertNews']).nthCalledWith(1, newsEntity) }) }) ... |
convertNewsの単体テストにおいて、Newsドメインにファクトリメソッドであるfromメソッドをmockする方法がわかりました。
1 2 3 4 5 | private convertNews(newsEntity: NewsEntity[]): News { const news = News.from(newsEntity) return news } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | ... describe('convertNews', () => { it('ニュースドメインに変換することができる', async () => { const newsEntity = mock<NewsEntity[]>() const news= mock<News>() const from = jest.spyOn(News, 'from') .mockImplementation((_: NewsEntity[]): News => { return news; }) const actual = newsGateway['convertNews'](newsEntity) expect(actual).toEqual(news) expect(from).toBeCalled() }) }) ... |
まずspyOnでNewsドメインのfromメソッドをmockします。mockImplementation() 関数の引数は、以下のようになっています。
- 第1引数:モックするメソッドの引数型
- 第2引数:モックするメソッドの戻り値型
- 第3引数:モックするメソッドの処理本体
この場合、第1引数は NewsEntity[] 型、第2引数はNews型、第3引数はNews型のオブジェクトを返す処理です。つまり、from() メソッドにNewsEntity[]型のエンティティを渡すと、常にnewsを返すように設定しています。
convertNewsはprivateメソッドなので、newsEntityを引数rにnewsGateway[‘convertNews’]の形で呼び出します。
あとは結果が正しいかと、mockしたfromメソッドが呼び出されたかを確認しています。