【TypeScript】【Jest】TypeError: Cannot read property 'catch' of undefined
- typescript 3.5.1
- jest 24.8.0
- typeorm 0.2.18
import faker from 'faker' import { deleteSchedule } from '~/domain/deleteSchedule' import { ScheduleRepository } from '~/repository/ScheduleRepository' import { scheduleFactory } from '~/test/factory/scheduleFactory' import { DeleteResult } from 'typeorm' jest.mock('~/repository/ScheduleRepository') let scheduleRepository: ScheduleRepository let scheduleID: number beforeEach(() => { ;((ScheduleRepository as any) as jest.Mock<ScheduleRepository>).mockClear() scheduleRepository = new ScheduleRepository() scheduleID = faker.random.number() }) describe('deleteSchedule', () => { test('正常系', async () => { await deleteSchedule({ client, event, scheduleRepository, scheduleID }) }) })
このようにRepositoryをモックしてテストを実行すると、
TypeError: Cannot read property 'catch' of undefined
とエラーが出る。
動作コードは下のようになっている。
const schedule = await data.scheduleRepository .findOne(data.scheduleID) .catch(() => Promise.reject(new Error('findOne failed'))) if (schedule == null) return Promise.reject(new Error('schedule is null')) await data.scheduleRepository .delete(data.scheduleID) .catch(() => Promise.reject(new Error('delete failed')))
.catch
の部分でレシーバがundefinedになっているのが駄目なようだ。
jest.mock('./sound-player') を呼ぶと、便利な "自動モック" を返してくれます。これは、クラスのコンストラクタおよびすべてのメソッドの呼び出しをスパイするのに使用できます。 この関数は ES6 クラスをモックコンストラクタに置き換え、すべてのメソッドを、常に undefined を返すモック関数に置き換えます。
モックしたクラスのメソッドはundefinedを返す。 Promiseが返らないのでthenやcatchは生えないというわけだ。
モックインスタンスのメソッドでPromise.resolveを返すには mockResolvedValue
mockResolvedValueOnce
を使う。
(Promise.rejectを返す場合は mockRejectedValue
)
beforeEach(() => { ;((ScheduleRepository as any) as jest.Mock<ScheduleRepository>).mockClear() scheduleRepository = new ScheduleRepository() ;((scheduleRepository as any) as jest.Mocked< ScheduleRepository >).findOne.mockResolvedValueOnce(new Schedule()) // 追加 ;((scheduleRepository as any) as jest.Mocked< ScheduleRepository >).delete.mockResolvedValueOnce(new DeleteResult()) // 追加 scheduleID = faker.random.number() })
このようにすればテストが通った。