Stub moment.js 构造函数与 Sinon

Stub moment.js constructor with Sinon

我无法在使用 format 函数将 moment 构造函数调用到 return 预定义字符串时存根,这是我想要的示例规范运行 与 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(...) 调用?

我在 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 */

})

很难从描述中分辨出来,但是如果您尝试对 moment 构造函数进行存根(而不是其他 lib 功能)的原因是因为您试图控制 Moment 的日期 returns (为了更可靠的测试),你可以使用 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;
});

如果其他所有方法都失败,请尝试将其添加到您的测试套件中;

moment.prototype.format = sinon.stub().callsFake(() => 'FOOBARBAZ');