如何使用 sinon 存根 new Date()?

Posted

技术标签:

【中文标题】如何使用 sinon 存根 new Date()?【英文标题】:How do I stub new Date() using sinon? 【发布时间】:2015-10-13 23:30:08 【问题描述】:

我想验证各种日期字段是否已正确更新,但我不想预测何时调用 new Date()。如何存根 Date 构造函数?

import sinon = require('sinon');
import should = require('should');

describe('tests', () => 
  var sandbox;
  var now = new Date();

  beforeEach(() => 
    sandbox = sinon.sandbox.create();
  );

  afterEach(() => 
    sandbox.restore();
  );

  var now = new Date();

  it('sets create_date', done => 
    sandbox.stub(Date).returns(now); // does not work

    Widget.create((err, widget) => 
      should.not.exist(err);
      should.exist(widget);
      widget.create_date.should.eql(now);

      done();
    );
  );
);

如果相关,这些测试在节点应用程序中运行,我们使用 TypeScript。

【问题讨论】:

【参考方案1】:

怀疑你想要useFakeTimers函数:

var now = new Date();
var clock = sinon.useFakeTimers(now.getTime());
//assertions
clock.restore();

这是纯 JS。一个有效的 TypeScript/javascript 示例:

var now = new Date();

beforeEach(() => 
    sandbox = sinon.sandbox.create();
    clock = sinon.useFakeTimers(now.getTime());
);

afterEach(() => 
    sandbox.restore();
    clock.restore();
);

【讨论】:

太棒了,看起来它可以满足我的需求。一旦我得到一个最终工作的版本,我会把它编辑成你的答案并接受它。 从 sinon v5 开始,sinon 对象是一个跟踪 sinon.useFakeTimers 的沙箱,可以用 sinon.restore() 调用,允许 sandboxclock 变量在以上要删除:sinonjs.org/guides/… 这里只是一个小观察:当你使用沙盒时(你应该这样做),你不需要clock.restore(),因为沙盒会处理它【参考方案2】:

sinon.useFakeTimers() 出于某种原因破坏了我的一些测试,我不得不存根 Date.now()

sinon.stub(Date, 'now').returns(now);

在这种情况下,在代码中而不是 const now = new Date(); 你可以这样做

const now = new Date(Date.now());

或者考虑使用moment 库来获取与日期相关的内容。存根很容易。

【讨论】:

这对我有用,除了Date.now() 返回一个时间戳,所以我认为now 方法应该使用Date.now() 返回的时间戳进行存根,而不是使用new Date() 创建一个新日期.基本上第二行应该是:const now = Date.now();【参考方案3】:

我在寻找解决方案时发现了这个问题,如何仅模拟 Date 构造函数。 我想在每次测试中使用相同的日期,但要避免嘲笑 setTimeout。 诗乃在内部使用lolex 我的解决方案是将对象作为参数提供给 sinon:

let clock;

before(async function () 
    clock = sinon.useFakeTimers(
        now: new Date(2019, 1, 1, 0, 0),
        shouldAdvanceTime: true,
        advanceTimeDelta: 20
    );
)

after(function () 
    clock.restore();
)

您可以在lolex API 中找到其他可能的参数

【讨论】:

这个答案令人难以置信,展示了有关 sinon/lolex API 的知识。它应该被标记为正确,因为它还解决了在测试中需要大量clock.tick()s。

以上是关于如何使用 sinon 存根 new Date()?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 sinon 存根/模拟从“超类”复制的依赖项方法

轻松清理 sinon 存根

使用 Sinon 存根 window.location.href

用 sinon 模拟/存根猫鼬 findById

使用 sinon 为 redux 操作存根闭包函数

用 sinon 存根,用 chai 测试