web-dev-qa-db-ja.com

Sinonを使用したスタブmoment.jsコンストラクター

moment関数で呼び出して、事前定義された文字列を返すときにformatコンストラクターをスタブ化できません。これは、mochaで実行したい仕様の例です。

it('should stub moment', sinon.test(function() {
  console.log('Real call:', moment());

  const formatForTheStub = 'DD-MM-YYYY [at] HH:mm';
  const momentStub = sinon.stub(moment(),'format')
                      .withArgs(formatForTheStub)
                      .returns('FOOBARBAZ');

  const dateValueAsString = '2025-06-01T00:00:00Z';

  const output = moment(dateValueAsString).format(formatForTheStub);

  console.log('Stub output:',output);
  expect(output).to.equal('FOOBARBAZ');

}));

console.logを使用してこの出力を確認できます。

Real call: "1970-01-01T00:00:00.000Z"
Stub output: 01-06-2025 at 01:00

しかし、テストが失敗すると01-06-2025 at 01:00 !== 'FOOBARBAZ'moment(something).format(...)呼び出しを適切にスタブするにはどうすればよいですか?

15
TPPZ

私は答えを見つけました http://dancork.co.uk/2015/12/07/stubbing-moment/

どうやらmomentは.fnを使用してプロトタイプを公開しているので、次のことができます。

import { fn as momentProto } from 'moment'
import sinon from 'sinon'
import MyClass from 'my-class'

const sandbox = sinon.createSandbox()

describe('MyClass', () => {

  beforeEach(() => {
    sandbox.stub(momentProto, 'format')
    momentProto.format.withArgs('YYYY').returns(2015)
  })

  afterEach(() => {
    sandbox.restore()
  })

  /* write some tests */

})
20
IanVS

説明から判断するのは難しいですが、momentコンストラクター(残りのlib機能ではない)をスタブしようとしている理由が、Momentが返す日付を制御しようとしているためである場合(より信頼性の高いテストのため)、 SinonのusefakeTimerを使用してこれを行います。そのようです:

// Set up context for mocha test.
      beforeEach(() => {
        this.clock = date => sinon.useFakeTimers(new Date(date));
        this.clock('2019-07-07'); // calling moment() will now return July 7th, 2019.
      });

次に、特定の日付の前後で逆ロジックをテストする必要がある他のテストのコンテキストで日付を更新できます。

it('changes based on the date', () => {
  this.clock('2019-09-12');
  expect(somethingChanged).to.be.true;
});
6
Lauren