web-dev-qa-db-ja.com

new Date()のようなコンストラクタをモックする方法

_new Date_に依存して日付オブジェクトを作成し、それを操作するメソッドがあります。私は操作が期待どおりに機能することをテストしているので、返された日付を期待された日付と比較する必要があります。そのためには、テストでもテストされるメソッドでも_new Date_が同じ値を返すことを確認する必要があります。どうやってやるの?

コンストラクター関数の戻り値を実際にモックする方法はありますか?

日付オブジェクトを提供し、モックできる関数で必要となるモジュールを作成できます。しかし、それは私のコードでは不必要な抽象化のようです。

テストする関数の例...

_module.exports = {
  sameTimeTomorrow: function(){
    var dt = new Date();
        dt.setDate(dt + 1);
    return dt;
  }
};
_

new Date()の戻り値をモックするにはどうすればよいですか?

23
Seth Feldkamp

ジャスミンのspyOn(jestはジャスミン上に構築されています)を使用して、次のようにgetDateの日付のプロトタイプをモックできます。

spyOn(Date.prototype, 'setDate').and.returnValue(DATE_TO_TEST_WITH);

SpyOnは、それ自体が終了した後もクリーンアップし、テストの範囲でのみ持続します。

12
linuxdan

以下のようにjest.spyOnを使用して、new Date()のようなコンストラクターをモックできます。

test('mocks a constructor like new Date()', () => {
  console.log('Normal:   ', new Date().getTime())

  const mockDate = new Date(1466424490000)
  const spy = jest
    .spyOn(global, 'Date')
    .mockImplementation(() => mockDate)

  console.log('Mocked:   ', new Date().getTime())
  spy.mockRestore()

  console.log('Restored: ', new Date().getTime())
})

出力は次のようになります。

Normal:    1566424897579
Mocked:    1466424490000
Restored:  1566424897608
8
Yuci

指定された日付値で構築されたDateオブジェクトを返すモック関数を使用して、Dateコンストラクターをオーバーライドできます。

var yourModule = require('./yourModule')

test('Mock Date', () => {
  const mockedDate = new Date(2017, 11, 10)
  const originalDate = Date

  global.Date = jest.fn(() => mockedDate)
  global.Date.setDate = originalDate.setDate

  expect(yourModule.sameTimeTomorrow().getDate()).toEqual(11)
})

ここで例をテストできます: https://repl.it/@miluoshi5/jest-mock-date

7
Miluoshi

Dateコンストラクタを、常にハードコードされた日付を返すものに置き換え、完了したら通常に戻すことができます。

var _Date = null;

function replaceDate() {
  if (_Date) {
    return
  };

  _Date = Date;

  Object.getOwnPropertyNames(Date).forEach(function(name) { 
    _Date[name] = Date[name] 
  });

  // set Date ctor to always return same date
  Date = function() { return new _Date('2000-01-01T00:00:00.000Z') }

  Object.getOwnPropertyNames(_Date).forEach(function(name) { 
    Date[name] = _Date[name] 
  });  
}

function repairDate() {
  if (_Date === null) {
    return;
  }

  Date = _Date;
  Object.getOwnPropertyNames(_Date).forEach(function(name) { 
    Date[name] = _Date[name] 
  });  

  _Date = null;
}

// test that two dates created at different times return the same timestamp
var t0 = new Date();

// create another one 100ms later
setTimeout(function() {
  var t1 = new Date();

  console.log(t0.getTime(), t1.getTime(), t0.getTime() === t1.getTime());

  // put things back to normal when done
  repairDate();
}, 100);
1
Ben Taber

私はちょうどjestテストを書いて、new Date()global.Date = () => nowでスタブすることができました

1
David

date-faker を使用して、新しいDate()またはDate.now()が返すものを模擬できます。

import { dateFaker } from 'date-faker'; // var { dateFaker } = require('date-faker');

// will return tomorrow, shift by one unit
dateFaker.add(1, 'day'); 

// shift by several units
dateFaker.add({ year: 1, month: -2, day: 3 });

// set up specific date, accepts Date or time string
dateFaker.set('2019/01/24'); 

dateFaker.reset();
0
MatGar