JasmineのテストでMoment.jsをイイ感じに比較する
JavaScriptの日付ライブラリといえばMoment.js。標準のDateと比較するととても便利です。ただMoment.jsは内部のデータの持ち方が複雑で、ユニットテストで度々問題になります(私はなりました)。
Jasmineでユニットテストを記述するときにイイ感じに比較する方法を紹介します。
JasmineのaddCustomEqualityTesterを使用して一致判定をカスタマイズする
Jasmine標準の toEqual
を使うだけでもオブジェクトの広い範囲で一致判定させることができますが、Jasmineには一致判定される対象をカスタマイズする機能が備わっています。 addCustomEqualityTester
で一致判定を行う関数を追加すると、任意の対象を等しいと判定させることができます。
標題の通りMoment.jsを一致判定させてみます。まずは必ずコケるMoment.jsのテスト例です。
import * as moment from 'moment'; it('Moment.js equality', () => { expect(moment('2019-01-01T01:02:03.123')).not.toEqual('2019-01-01T01:02:03.123' as any); expect(moment('2019-01-01T01:02:03.123')).not.toEqual(new Date('2019-01-01T01:02:03.123') as any); expect(moment('2019-01-01T01:02:03.123')).toEqual(moment([2019, 0, 1, 1, 2, 3, 123])); });
このテストを実行すると3個目のexpectがNG判定となります。
Error: Expected object not to have properties _f: 'YYYY-MM-DDTHH:mm:ss.SSSS' at <Jasmine> at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/test.ts:40:45) at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:359:1) at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:308:1)
ここに addCustomEqualityTester
でMoment.jsを一致させるコードを追加します。先ほどはコケていたテストコードが無事通過するようになります。
import { isMoment } from 'moment'; import * as moment from 'moment'; beforeAll(() => { jasmine.addCustomEqualityTester((a, b) => { if (!isMoment(a) || !isMoment(b)) { // 両者ともMoment.jsでは無いので検証対象外 => undefinedを返す return; } // どちらかがMoment.jsなので確実にtrue/falseを返す return isMoment(a) && a.isSame(b); }); }); it('Moment.js equality', () => { expect(moment('2019-01-01T01:02:03.123')).not.toEqual('2019-01-01T01:02:03.123' as any); expect(moment('2019-01-01T01:02:03.123')).not.toEqual(new Date('2019-01-01T01:02:03.123') as any); expect(moment('2019-01-01T01:02:03.123')).toEqual(moment([2019, 0, 1, 1, 2, 3, 123])); });
addCustomEqualityTester
は beforeAll
beforeEach
it
のいずれかのスコープ内で記述する必要がある点にだけ注意してください。