【问题标题】:How To "Fake" Date/Time For Testing Mongoose Models如何“伪造”测试 Mongoose 模型的日期/时间
【发布时间】:2018-06-03 13:43:57
【问题描述】:

在此之前,感谢您提供的任何帮助/建议!

我正在努力实现的目标

在创建 Mongoose 模型的实例时,我正在尝试寻找一种优雅的方式来测试日期/时间。

我想确保存储的时间是正确的。

我的模型目前看起来像这样:

const messageSchema = mongoose.Schema({
  user: { type: String, required: true },
  message: { type: String, required: true },
  created: { type: Date, default: Date.now },
});

const Message = mongoose.model('Message', messageSchema);

我将此模型导入 mocha 测试套件,并尝试按照以下方式运行测试:

const now = {Date message was created}
it('check time matches time created', () => {
  expect(message.created).to.equal(now);
});

到目前为止我已经尝试过什么

我尝试实现这一点的方法是使用Sinon's Fake timers 功能。

所以我的测试用例是这样的:

describe('creating new message', () => {
  let clock;
  let message;
  let now;

  before(() => {
    clock = sinon.useFakeTimers();
    clock.tick(100);
    message = new Message({
      user: 'Test User',
      message: 'Test Message',
    });
    // Time the message was created
    now = Date.now();
    clock.tick(100);
  });

  it('check time matches time created', () => {
    expect(message.created).to.equal(now);
  });
});

为什么我认为这不起作用

我认为这是行不通的,因为作为 Mongoose 模型默认传递的 Date.now 函数与 Sinon 假计时器隔离(假计时器在测试文件中,模型是从另一个文件)。

再次感谢您!

【问题讨论】:

    标签: node.js mongodb unit-testing mongoose sinon


    【解决方案1】:

    解决方案

    只需将Date.now 包装在一个匿名函数中,就像这样:

    function() { return Date.now(); }
    

    或 ES6 版本

    () => Date.now()
    

    所以架构会变成这样:

    const messageSchema = mongoose.Schema({
       user: { type: String, required: true },
       message: { type: String, required: true },
       created: { type: Date, default: () => Date.now() },
    });
    

    为什么有效?

    因为你在做sinon.useFakeTimers()的时候,sinon在后面做的就是覆盖global属性Date

    并且调用Date 与调用global.Date 相同。

    当您将Date.now 传递给mongoose 时,您实际上是在传递global.Date 引用的Node 内部方法,而mongoose 将调用此方法,而无需访问global.Date 参考了。

    但是,在我的解决方案中,我们传递了一个方法,当调用该方法时,它会访问global.Date引用,现在它已被Sinon 存根。

    为了在实践中看到这种行为,您可以在 Javascript 中执行以下操作:

    var nativeDate = Date; // accessing global.Date
    Date = { now: () => 1 }; // overrides global.Date reference to a entirely new object
    console.log(Date.now()); // now it outputs 1
    console.log(nativeDate.now()); // outputs current date, stub doesn't work here, because it's calling the javascript native Date method, and not global.Date anymore
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-28
      相关资源
      最近更新 更多